11

from How to create a button programmatically?

self doesn't work in swift playground :

button.addTarget(self, action: "buttonAction:", forControlEvents: UIControlEvents.TouchUpInside)

error :

Playground execution failed: error: :42:13: error: use of unresolved identifier 'self'

I also tried to create a class with buttonAction method inside it compiles but when I click on the button nothing prints in console

import UIKit

class myself {


    func buttonAction(sender:UIButton!)
    {
        println("Button tapped")
    }

}

var s = myself()

// Create View
var f = CGRect(x:0,y:0,width:200,height:200)
var view = UIView(frame:f)


// Create Button
var b = UIButton(frame: f)
b.setTitle("Hello", forState: UIControlState.Normal)
b.addTarget(s, action: "buttonAction:", forControlEvents: UIControlEvents.TouchUpInside)

view.addSubview(b)

view
Community
  • 1
  • 1
user310291
  • 36,946
  • 82
  • 271
  • 487
  • Is that your full code? You can't reference `self` outside of some sort of a class method – BergQuester Jun 08 '14 at 17:44
  • 1
    @BergQuester yes I know for self that's why I ask for alternative : how do I reference the playground where I would define buttonAction func ? I also tried to create a class myself but when I click button it doesn't print anything (see code update) – user310291 Jun 08 '14 at 18:57
  • I don't think this is possible, because right now swift playground can't simulate inputs. In this case touch events – Waruna Jun 08 '14 at 19:30
  • Gotcha. Yeah, the playgrounds aren't actually interactive. Yes, you can scrub back and forth in time in some cases, but you can't actually interact with the controls. – BergQuester Jun 08 '14 at 20:20
  • @BergQuester what a pity I'm crying :( – user310291 Jun 08 '14 at 20:58
  • I know! Join with me by filing a bug report for a feature request at http://bugreport.apple.com – BergQuester Jun 08 '14 at 22:05
  • Never use bugreport. When I go there I got empty list. – user310291 Jun 09 '14 at 14:09

3 Answers3

8

Unfortunately, controls in playgrounds are not interactive.

I tried getting around the non-interactivity of playground controls the other day by creating and displaying an NSWindow for a Mac playground, however, the result was that the window simply flashed behind the playground.

Best that I can tell after some probing into NSProcess, NSBundle, NSApplication and watching the system Activity Monitor, the playground actually compiles your code, loads it into a stub app, executes, the playground captures the results and displays them then the stub app exits or waits around for the next execution. This means by the time you see the results, the code is no longer executing.

If you're curious, you can try the code below in a playground to see what I mean. If you open Activity Monitor and filter on PlaygroundStub_OSX you can see the process that runs the code launch. It is oftentimes in a "Not responding" state. I've also included a screen capture of the results of the probing portion of the code.

import Cocoa

var app = NSApplication.sharedApplication()
app.hidden

var procInfo = NSProcessInfo.processInfo()
procInfo.processName
procInfo.arguments

var bundle = NSBundle.mainBundle()
bundle.bundlePath



var window = NSWindow(contentRect: NSRect(x: 30, y: 30, width: 400, height: 400), styleMask: NSTitledWindowMask, backing: .Buffered, defer: false)


var view = NSView(frame: NSRect(x: 0, y: 0, width: 300, height: 300))

var textField = NSTextField(frame: NSRect(x: 30, y: 30, width: 100, height: 20))

textField.stringValue = "Test"

view.addSubview(textField)

var button = NSButton(frame: NSRect(x: 30, y: 60, width: 100, height: 30))

button.highlight(true)

var buttonCell:NSButtonCell = button.cell() as NSButtonCell
buttonCell.bezelStyle = NSBezelStyle.RoundedBezelStyle


view.addSubview(button)

window.contentView.addSubview(view)



window.makeKeyAndOrderFront(nil)

enter image description here

UPDATE

I was able to get a semi-functional OS X window in a Swift playground and placed the code in a github repo. I'm not sure if an interactive UIKit based view is possible yet.

BergQuester
  • 6,167
  • 27
  • 39
8

With Xcode 7.3 this is now supported. You'll need to declare an ObjectiveC object or expose a function using @objc keyword as a target:

class Responder : NSObject {
    func action() {
        print("Button pressed!")
    }
}

let containerView = UIView(frame: CGRect(x: 0.0, y: 0.0, width: 375.0, height: 667.0))
XCPlaygroundPage.currentPage.liveView = containerView
let responder = Responder()

let button = UIButton(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
button.backgroundColor = UIColor.greenColor()
button.setTitle("TEST", forState: .Normal)
button.addTarget(responder, action: #selector(Responder.action), forControlEvents: .TouchUpInside)
containerView.addSubview(button)
MoFlo
  • 559
  • 4
  • 6
1

I do this successfully with Cocoa.

Make your class a subclass of NSObject. Create an NSWindow in your class and move the button and the action into your class. Then you can set the button's target to self.

Try it with UIKit and let us know if it works.

Gene De Lisa
  • 3,628
  • 1
  • 21
  • 36