KMT was right, I missed something.
I tested this, it works (IOS)
theButton.frame.size.height = 50
theButton.frame.size.width = 80
theButton.title = "Too long to fit on a single line"
theButton.titleLabel!.lineBreakMode = .byCharWrapping // .byWordWrapping may be better here
It is also very simple to do it in IB
set linebreak mode to word wrap or character wrap
For OSX, it seems more difficult
I had to use
theButton.cell!.lineBreakMode = .byCharWrapping
But it seems OSX computes height automatically, and I could not set it.
I had a trick to force height by adding \n at the end of button title, but result is so so.
To force height : you could use textured button (square)
https://stackoverflow.com/questions/17711836/unable-to-set-height-of-nsbutton
EDITED
I tested 3 solutions
// Sol1
let button = NSButton(frame: NSRect(x: 150, y: 200, width: 80, height: 65))
button.title = "A long text button\n"
button.cell!.lineBreakMode = .byWordWrapping
window!.contentView?.addSubview(button)
// Sol2
let button2 = NSButton(frame: NSRect(x: 250, y: 200, width: 80, height: 65))
button2.title = "A long text button"
button2.cell!.lineBreakMode = .byWordWrapping
window!.contentView?.addSubview(button2)
// Sol3
let button3 = NSButton(frame: NSRect(x: 350, y: 200, width: 80, height: 65))
button3.title = "\nA long text button\n"
button3.cell!.lineBreakMode = .byWordWrapping
window!.contentView?.addSubview(button3)
Solution 3 works best, with text well centered and wrapped on 3 lines ; it is easy to add \n at the beginning and at the end of title string.
Solution 2 does not work: I just get one line of truncated text
Solution 1 wiites the text a bit too high in the button
And a 4th one, to create the action and target
let button4 = NSButton(title: "\nA very long text button\n", target: self, action: nil)
button4.frame = CGRect(x: 250, y: 300, width: 100, height: 60)
button4.cell!.lineBreakMode = .byWordWrapping
window!.contentView?.addSubview(button4)
Result equivalent to 3 (but widyh needs to be a bit larger)
Hope that helps.