let point = convert(event.locationInWindow, from: nil) for index in0..<numberOfItems(inSection: 0) { let frame = frameForItem(at: index) ifNSMouseInRect(point, frame, isFlipped) { clickedIndex = index break } }
returnsuper.menu(for: event) } }
let menu = NSMenu() menu.addItem(NSMenuItem(title: "Delete", action: #selector(didSelectDelete(_:)), keyEquivalent: "")) collectionView.menu = menu
@objcfuncdidSelectDelete(_ item: NSMenuItem) { guard let index = collectionView.clickedIndex, index < notes.count else { return } let indexPath = IndexPath(item: index, section: 0) notes.remove(at: index) collectionView.deleteItems(at: Set(arrayLiteral: indexPath)) }
For NSCollectionView with more than 1 sections
1
let frame = layoutAttributesForItem(at: IndexPath(item: index, section: 0))?.frame ?? .zero
Use Omnia
Omnia supports clicked indexPath for multi section NSCollectionView
1 2 3
collectionViewHandler.addMenuItem(title: "Add to Favorite", action: { item in print(item) })
extension MainView: NSTextViewDelegate { func textViewDidChangeSelection(_ notification: Notification) { // Change text color again after image dragging } }
ATSApplicationFontsPath (String - macOS) identifies the location of a font file or directory of fonts in the bundle’s Resources directory. If present, macOS activates the fonts at the specified path for use by the bundled app. The fonts are activated only for the bundled app and not for the system as a whole. The path itself should be specified as a relative directory of the bundle’s Resources directory. For example, if a directory of fonts was at the path /Applications/MyApp.app/Contents/Resources/Stuff/MyFonts/, you should specify the string Stuff/MyFonts/ for the value of this key.
But in places where using UIViewController and manage their view controller containment hierarchy is not desired, then we can roll out a normal object to act as the controller.
The reason is that window is released upon closed if it is not owned by NSWindowController, or we can use releasedWhenClosed
The value of this property is YES if the window is automatically released after being closed; NO if it’s simply removed from the screen.
The default for NSWindow is YES; the default for NSPanel is NO. Release when closed, however, is ignored for windows owned by window controllers. Another strategy for releasing an NSWindow object is to have its delegate autorelease it on receiving a windowShouldClose: message.
extensionHorizontalUsersViewController: UIScrollViewDelegate{ funcscrollViewDidEndDecelerating(_ scrollView: UIScrollView) { let point = view.convert(collectionView.center, to: collectionView)
If you don’t want to use https://github.com/onmyway133/EasyClosure yet, it’s easy to roll out a closure based UIButton. The cool thing about closure is it captures variables
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
finalclassClosureButton: UIButton{ var didTouch: (() -> Void)?
This year I’m lucky enough to get the ticket to WWDC and I couldn’t be more satisfied. 5 conference days full of awesomeness, talks, labs and networking, all make WWDC special and memorial conference for every attendee.
As predicted by many, Marzipan (now officially called Project Catalyst) a technology that could allow iOS apps to be ported to macOS, would be the main topic for this year. But WWDC went more spectacular than that, with dark mode on iOS, independent watchOS apps, and SwiftUI being the star of the show. With over 150 sessions and extra videos, it can be a bit overwhelming to catch up, so I sum up 10 essential sessions to get started. It’s good to catch up with the latest technology, but be aware that frameworks and APIs come and get deprecated very often. It’s better to understand why they are introduced, how to learn the skills and mindset so we can apply them in our apps to delight user experience.
Firstly, a little tip to get the most of WWDC videos. Although you can watch on Apple developer website, there’s WWDC for macOS app that allows much more comfortable watching experience. There we can tweak playing speed, picture in picture view mode, favorite and download videos for offline watching.
Secondly, for those of you who want to search some texts in the talks, there is ASCIIwwdc that provides full transcripts of all the talks.
If you only have time for 1 video, this is it. Right after the Keynote, Platform State of the Union is like keynote for developers as it highlights important development changes.
macOS 10.15, iOS 13, watchOS 6 and tvOS 13: As usual we get version bumps on all major platforms, which brings lots of new features and enhancement. macOS 10.15 is caleld Catalina and there’s a whole new platform for iPad called iPadOS.
Security and Privacy: Adding to security enhancement from last year, this year shows how Apple really commits into this. There are one-time location permission, signing with Apple, security protocol for HomeKit, new crypto framework which marks MD5 as insecure. Also, apps that target kids can’t display ad or include analytics.
tvOS 13 gets multiple user support
watchOS 6 makes way for independent watch apps, which does not require accompanying iOS apps. There’s also dedicated watch appstore.
iOS 13 now can live in the dark, but dropping support for iPhone 5S, 6 and below. Also, there is ability to toggle language setting per app only.
iPadOS is a spinoff version of iOS for now, they look the same but they are expected to take different paths. It includes mouse support and requires iPad Air 2 and newer devices.
macOS 10.15 introduces a replacement of bash with zsh. It also supports SideCar which allows iPad as an external display. Last but not least, there is Project Catalyst that enables iPad apps to run on the mac.
Xcode 11 includes Swift 5.1 that can target latest SDKs. It brings a new look and feel with tons of features like minimap, Xcode preview, official support for Swift Package Manager, source control enhancement and test plan.
Although Swift is developed in the open, it’s easy to lose track of in tons of proposals and changes. Swift 5.1 brings lots of cool features that power SwiftUI and Combine, so it’s a prerequisite.
Module stability: This looks unimportant but this may be the most key feature of Swift 5.1. Unlike ABI stability we get in Swift 5, module stability helps resolves differences at compile time. In other words, this ensures a Swift 5 library will work with the future Swift compilers.
A single expression can be declared without return keyword
Function builder, with marker @_functionBuilder which works pretty much like function with receiver in Kotlin, allows for some very neat DSL syntax.
Property wrapper, a counterpart of Kotlin delegated property, allows property accessors to be used in a convenient way. Shipped with Swift 5.1, we can use that with @propertyWrapper annotation.
Opaque return type with some keyword remedies limitation of Swift protocol with Self or associcated types requirements.
Among other things, there are other cool features like universal Self, static subscripts, collection diffing and matching against optional.
Welcome to the spotlight of WWDC 2019, SwiftUI. It may be the most exciting announcement since Swift was introduced in 2014. SwiftUI is not just a new framework, it’s a complete paradigm shift from imperative programming with UIKit/AppKit to a declarative world. I was amazed by how quickly React and Flutter allows fast prototyping and developing, so I’m very happy Apple finally makes this available natively on all platforms.
The cool thing about SwiftUI is that it is expressive and has consistent syntax across platforms. So it is a learn once, write anywhere concept. Together with hot reloading of Xcode Preview, this ends the long debate among iOS community about whether to write UI in code or Storyboard, as the source of truth is now the concise code, but users are free to change any UI details via interactive Preview.
Not only SwiftUI handles consistent UI according to Apple design guideline, it also provides many features for free like accessibility, dark mode and other bookkeeping.
SwiftUI supports latest platform versions and no backward compatibility, so some of us have to wait 1 or 2 more years until iOS 13 is widely adopted. To learn more about SwiftUI, there are other advanced sesions like
As much as I was excited about Dark theme in Android Q, Dark Mode in iOS is something that eases my eyes. Some apps also support Dark theme by their owns, but with iOS 13, supporting Dark mode to our apps is not a daunting task. There are more vibrancy materials, system colors that adapts automatically to dark and light modes. We can also select images for each mode in Asset Catalog easily.
Combine is a unified declarative framework for processing values over time. As a huge fan of Rx, Combine looks like home. It was thrilled to see this finnaly get supported official by Apple. This simplifying asyncrhonous programming a lot, also streamline other communication patterns like KVO and notification center.
Combine is the force the powers reactive nature in SwiftUI with Binding and BindableObject. There’s also lots of improvements to Foundation like collection diffing, new list and relative formatters, and notably Combine syntax for URLSession, which makes networking a breeze.
To learn more about Combine, there’s Combine in Practice where we can learn more about error handling, schedule work and many operators on streams.
Take a look at this talk to learn about new features in iOS 13 that we should be aware in our apps. Newly in iOS 13, we can take advantage of card style modal presentation that is very cumbersome to replicate ourselves. There’s also new UISearchBarTextField with advanced customizations for token and inputs. Lastly, the new UIMenu makes showing context menu trivial and make way for iPad apps to behave like native on the mac.
If you’re developing iOS apps, chances are that you have already stumbled upon API Design Guidelines which contains valuable guides to structuring our Swift code.
This highlights my most favorite programming advice “Clarity at the point of use”, because things we declare are written only once, but read many many times, so we should make those concise and clear. There’s also mention of preferring generic over protocol which reminds me of protocol witness technique.
This talk details how Apple engineers themselves design Swift code in their RealityKit and SwiftUI frameworks.
The launch time of your app can be decisive in user experience, it needs to be fast and do just the necessary things. With enhancements via shared and cached frameworks, apps now load faster on iOS 13. But there’s more thing we can do to improve this, thanks to the new App Launch profiler in Xcode 11, together with app launch time measurement in XCTests. The 3 words we can take away from this talk is minimize, prioritize, and optimize work at this critical launch time.
Starting with iOS 13 with Project Catalyst, there’s a new target environment check called UIKitForMac, which allows iPad apps to target the mac while using the same code base. Most of the UI after porting have the correct look and feel like a native macOS app with many features provided for free like window management. There are, kind of obviously, some frameworks that are designed specifically for phone and tablet experience, can’t be supported in macOS.
watchOS finally gets its own Appstore and the ability to run independent watchOS apps without a companying iOS app. With the introduction of URLSession and streaming APIs for the watch, together with enhancements in push notifications, Apple sign in, debugging, this can’t be a better time to start developing for the watch.
It is stunning to see how Apple comes up with so many cool announcements this year while keeping innovation and quality high. There are more sessions to explore, head over to WWDC 2019 developer website to learn more.
Should design image with enough height, transparent background and indicator at the bottom
Use this property to specify a custom selection image. Your image is rendered on top of the tab bar but behind the contents of the tab bar item itself. The default value of this property is nil, which causes the tab bar to apply a default highlight to the selected item
As you know, in the Pragmatic Programmer, section Your Knowledge Portfolio, it is said that
Learn at least one new language every year. Different languages solve the same problems in different ways. By learning several different approaches, you can help broaden your thinking and avoid getting stuck in a rut. Additionally, learning many languages is far easier now, thanks to the wealth of freely available software on the Internet
I see learning programming languages as a chance to open up my horizon and learn some new concepts. It also encourage good habit like immutability, composition, modulation, …
I’d like to review some of the features of all the languages I have played with. Some are useful, some just make me interested or say “wow”
Curly braces
Each language can have its own style of grouping block of code, but I myself like the curly braces the most, which are cute :]
Some like C, Java, Swift, … use curly braces
Swift
init(total: Double, taxPct: Double) {
self.total = total
self.taxPct = taxPct
subtotal = total / (taxPct + 1)
}
Some like Haskell, Python, … use indentation
Haskell
bmiTell :: (RealFloat a) => a -> String
bmiTell bmi
| bmi <= 18.5 = "You're underweight, you emo, you!"
| bmi <= 25.0 = "You're supposedly normal. Pffft, I bet you're ugly!"
| bmi <= 30.0 = "You're fat! Lose some weight, fatty!"
| otherwise = "You're a whale, congratulations!"
Some like Elixir use keyword list
ELixir
if false, do: :this, else: :that
Named parameter
Language like Objective C, Swift offer named parameter, which make it easier to reason about a function call
func sayHello(to person: String, and anotherPerson: String) -> String {
return "Hello \(person) and \(anotherPerson)!"
}
Explicit type
Language like C, Swift, Java, … have type information in parameter and in return, which make it easier to reason about a function call
Languages like Haskell, Python, Elixir, support list comprehension
Elixir
iex> for n <- [1, 2, 3, 4], do: n * n
[1, 4, 9, 16]
First class function
I enjoy functional programming, so first class function support in Javascript, Swift, Haskell, Elixir, … really make me happy
Haskell
zipWith' (*) (replicate 5 2) [1..]
Curry
Currying is the technique of translating the evaluation of a function that takes multiple arguments (or a tuple of arguments) into evaluating a sequence of functions, each with a single argument (partial application)
Language like Swift 2, Haskell, … have curry by default. Some like Javascript can use libraries (Lodash, …) to achieve this. In Haskell, every function officially only takes one parameter.
The |> symbol used in the snippet above is the pipe operator: it simply takes the output from the expression on its left side and passes it as the first argument to the function call on its right side
Haskell often takes advantage of this custom -: operator Haskell
x -: f = f x
(0,0) -: landLeft 1 -: landRight 1 -: landLeft 2
Functor, Applicative Functor, Monoid, Monad
I really like enjoy Haskell because of these typeclasses. It realizes common pattern (map, apply, join, bind, …) with comptutational context. It really enlightens me when I find that function is a Monad as well (you should read the Reader monad)
Haskell
instance Monad Maybe where
return x = Just x
Nothing >>= f = Nothing
Just x >>= f = f x
fail _ = Nothing
landLeft :: Birds -> Pole -> Maybe Pole
landLeft n (left,right)
| abs ((left + n) - right) < 4 = Just (left + n, right)
| otherwise = Nothing
landRight :: Birds -> Pole -> Maybe Pole
landRight n (left,right)
| abs (left - (right + n)) < 4 = Just (left, right + n)
| otherwise = Nothing
ghci> return (0,0) >>= landLeft 1 >>= banana >>= landRight 1
Nothing
List comprehension in Haskell is just syntactic sugar for using lis as Monad Haskell
enum Result<T> {
case Value(T)
case Error(NSError)
}
extension Result {
func map<U>(f: T -> U) -> Result<U> {
switch self {
case let .Value(value):
return Result<U>.Value(f(value))
case let .Error(error):
return Result<U>.Error(error)
}
}
}
extension Result {
static func flatten<T>(result: Result<Result<T>>) -> Result<T> {
switch result {
case let .Value(innerResult):
return innerResult
case let .Error(error):
return Result<T>.Error(error)
}
}
}
extension Result {
func flatMap<U>(f: T -> Result<U>) -> Result<U> {
return Result.flatten(map(f))
}
}
Trait and mixin
Languages like Scala, … support trait
Similar to interfaces in Java, traits are used to define object types by specifying the signature of the supported methods. Unlike Java, Scala allows traits to be partially implemented; i.e. it is possible to define default implementations for some methods
Scala
trait Similarity {
def isSimilar(x: Any): Boolean
def isNotSimilar(x: Any): Boolean = !isSimilar(x)
}
class Point(xc: Int, yc: Int) extends Similarity {
var x: Int = xc
var y: Int = yc
def isSimilar(obj: Any) =
obj.isInstanceOf[Point] &&
obj.asInstanceOf[Point].x == x
}
module Greetings
def hello
puts "Hello!"
end
def bonjour
puts "Bonjour!"
end
def hola
puts "Hola!"
end
end
class User
include Greetings
end
Delegate property
There are certain common kinds of properties that would be very nice to implement once and for all like lazy, observable and storing. An example is in Kotlin
class Delegate {
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
return "$thisRef, thank you for delegating '${property.name}' to me!"
}
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
println("$value has been assigned to '${property.name}' in $thisRef.")
}
}
Where to go from here
Hope you find something interesting. Each language has its own pros and is designed for specific purpose. So no list will be enough to cover them all.
To take a quick peek into other programming languages, I find Learn in One Video by Derek very helpful.
There are things that intrigue us every day like Swift initialization rule make it explicit when using initializer, Go goroutine and channel for concurrent code, Elixir process for easy concurrent and message communication. You’ll be amazed by how process encapsulates state, Haskell data type encourages immutability and thread safe code, Elixir macro for great extension of the language. The best way to to learn is to use and dive into the languages often.
let replicatorLayer = CAReplicatorLayer() let animation = CABasicAnimation(keyPath: #keyPath(CALayer.opacity))
let line = CALayer() let lineCount: Int = 12 let duration: TimeInterval = 1.0 let lineSize: CGSize = CGSize(width: 20, height: 6) let lineColor: UIColor = UIColor.darkGray
let angle = CGFloat.pi * 2 / CGFloat(lineCount) let rotation = CATransform3DMakeRotation(angle, 0, 0, 1.0)
// x: // y: half the height, changing affects rotation of lines line.position = CGPoint(x: 48, y: 75)
line.add(animation, forKey: nil)
Pay attention to position of the line. The larger the x, the closer to center. y should be half the height of the replicator layer size, changing it affects the skewness of the line.
CAAnimation is about presentation layer, after animation completes, the view snaps back to its original state. If we want to keep the state after animation, then the wrong way is to use CAMediaTimingFillMode.forward and isRemovedOnCompletion