Getting error about "no member 'setTitle'" on my button - ios

I'm getting the wrong message from Xcode about my piece of code (which is perfectly fine). I posted a screenshot of my work. Please help me with this so I can do the rest.

With lightButton you are calling an IBAction you defined before (which is actually highlighted by Xcode, by the way). Since your IBAction doesn't return anything, you can't access any properties.
Value of type '(UIButton) -> ()' has no member 'setTitle'.
The (_) -> () syntax represents a function, where the first parentheses represent the function's arguments, the second one the return type.
You should define an IBOutlet which connects to the Storyboard.
class YourController: UIViewController {
#IBOutlet var myButton: UIButton?
// Usage:
func someFunction() {
myButton.setTitle('Title')
}
}

Related

This is one thing I do not understand in Swift

Consider these lines:
I create a NSButton based class with this:
typealias onClickHandler = (NSTextfieldSuper)->Void
var onClick: onClickHandler?
When the user clicks on an instance of that button, I do this:
if (self.onClick != nil) {
onClick?(self)
}
I use that button later, from another class, with this:
let button = SuperButton()
button.onClick = { (textField: NSTextfieldSuper)->Void in
}
I am not sure if this is the correct syntax. I would like to process the button sent from the first closure on the parent class, where the button is created.
This was the only form I was able to type this without Xcode complaining. If this is correct, what is the purpose of this ->Void there? What could this possibly returning?
I just want to process that button sent.
By the way, as a bonus, I have to initialize several buttons with this, all running the same function. It would be nice to do something like
func doSomething () {
}
and then
let button = SuperButton()
button.onClick = doSomething
any ideas?
This was the only form I was able to type this without Xcode complaining. If this is correct, what is the purpose of this ->Void there? What could this possibly returning?
It is the same as in your typealias, in Swift a function type has the form:
(parameter definitions) -> return type
and functions which return nothing have a return type of Void (similar to C). The full form off a closure expression is:
{ (parameter definitions) ->return typeinbody}
Without any inference this expression provides the full type of the closure, and the -> Void Return type in your example specifies that your closure returns nothing. In your assignment this full type will be checked at compile time to conform to the type of onClick.
Now Swift will infer lots of stuff and there are various shorthands available for closure expressions, you will find that Swift accepts:
button.onClick = { textField in }
as well here with both the argument and return types of the closure being inferred.
By the way, as a bonus, [...] any ideas?
Just make the types match:
func doSomething(textField : NSTextfieldSuper) { }
button.onClick = doSomething
Unlike in (Objective-)C functions and closures (blocks in C) are interchangeable (as they are in plenty of other languages, C is the oddfellow here)
HTH

Inconsistency in Swift optional protocol behaviour

Coming from .Net, I am trying to learn Swift3/iOS and got puzzled by the following apparent inconsistent behaviour of optional protocol members. I suspect its something got to do with the juggling between objc/swift words, but what am I missing here actually?
// In playground, given below:
#objc protocol SomePtotocol {
#objc optional func someMethod()
}
class SomeDelegate: NSObject, SomePtotocol {
}
class SomeController: NSObject {
var delegate: SomePtotocol = SomeDelegate()
}
// This works and compiles without error
let controller = SomeController()
controller.delegate.someMethod?() // No error, typed as '(() -> ())?'
// But this fails to even compile ??
let delegate = SomeDelegate()
delegate.someMethod?() // Error: 'SomeDelegate' has no member 'someMethod'
I would expect either both to fail or both pass, so if someone could please enlighten me on this anomaly.
The difference between the two blocks of code is the type of the variable involved.
In the first block, delegate is explicitly typed as SomePtotocol, and this protocol defines the someMethod method, so your statement is valid.
In the second block, delegate is implicitly typed as SomeDelegate and although this class conforms to SomePtotocol, it doesn't implement the optional method someMethod, so you get an error.
If you change your second block to
let delegate: SomePtotocol = SomeDelegate()
delegate.someMethod?()
which is equivalent to the first block, then there is no error.

Generics type constraint vs inheritance

Is there a difference between these two function declarations?
func doSomething<T: UIViewController>(controller: T) {...}
vs.
func doSomething(controller: UIViewController) {...}
In Type Constraint Syntax section of the Apples Swift programming language book, there's this code sample:
func​ ​someFunction​<​T​: ​SomeClass​, ​U​: ​SomeProtocol​>(​someT​: ​T​, ​someU​: ​U​) {
// function body goes here
}
with this description:
The hypothetical function above has two type parameters. The first type parameter, T, has a type constraint that requires T to be a subclass of SomeClass. ...
So in which cases is it better to use generic function described above?
They are different, but in the way you are using them, they amount to pretty much exactly the same result.
The difference is that when you call the generic version, the compiler sets T statically to be whatever type is passed in as the argument. When calling methods on that argument, this makes almost no difference – either way the calls on its methods will be dynamically dispatched, and you can't touch any parts of T that aren't guaranteed to be available from the constraint.
But suppose you made a change to this method to not just take an argument, but also return one, of the same type:
// T here will take the type of whatever is going in/out of the function
// be that UIViewController or a subtype of it
func doSomethingGenerically<T: UIViewController>(controller: T) -> T {
// some logic that results in a new controller being returned
}
// here the return type is fixed to be UIViewController
func doSomethingViaBaseClass(controller: UIViewController) -> UIViewController {
// some logic that results in a new controller being returned
}
Now, suppose you had a subclass of UIViewController that you were passing in, like so:
let subClass: MyUIViewController = ...
let controller1 = doSomethingGenerically(subClass)
let controller2 = doSomethingViaBaseClass(subClass)
Here, the type of the variable controller1 will be MyUIViewController, because that is what was passed in to the function so that is what T is. But the type of the variable controller2 will be UIViewController because that is the fixed type that doSomethingViaBaseClass returns.
Note, this doesn't mean the object they reference will be different - that depends on what the body of the function implements. It's just the type of the variables referring to it that will change.
There are other subtle differences but this is the main one to know about. In the case of structs, however, there are more differences worth noting. As it happens I wrote an article about them yesterday that might help.

protocol as parameter type in swift conflicts

I am using external SDK(by including their xcode project in my project).
The SDk was working properly in objective-c, but when I switched to swift, I am getting following problem.
Whenever I implementing delegate method where parameter is of type protocol, xcode suddenly gives error to object declaration of that Class which declared globally i.e. not in any function. If I comment that particular delegate method I will not get any error and it compile/executes successfully.
Please check the following swift code followed by my # comments
//CustomView is subclass of UIView
var customview : CustomView = CustomView() // #1 error as : Use of undeclared type CustomView
#IBAction func showCustomView(sender: AnyObject)
{
// CustomView configurations
}
#pragma CustomView Delegates
func CustomViewShown(view: AnyObject!) /// #2 delegate work properly
{
}
func CustomView(view: AnyObject!, didFailWithError error: NSError!)
// #3 if I keep this method uncommented it gives error to #1 line
// if I commented this method all other works fine without error.
{
}
Surprising thing is all the above delegate and SDK works fine for objective-C but not for swift.
On the basis of my little research, I am concluding that,
We can not use the Class name and method name same in swift, i.e. in my case its CustomView. If I am using CustomView for declaring object, I can not use it as method name.
so someone please verify that, I am correct or not ? and what is solution for this issue.
It's essentially a name conflicting problem.
Inside of your class declaration, CustomView is a method name, but not a class name. So, basically, your assumption is correct.
But, you have a workaround.
Let's suppose CustomView is declared in the SDK. And that is a framework named SomeSDK. Then you can reference the CustomView like this:
import SomeSDK
class ViewController: UIViewController {
var customview: SomeSDK.CustomView = SomeSDK.CustomView()
func CustomView(view: AnyObject!, didFailWithError error: NSError!) {
}
}
If you don't want to prefix SomeSDK. everywhere, you can typealias it:
import SomeSDK
typealias SDKCustomView = CustomView // you can use `CustomView` here because there is no conflicting name.
class ViewController: UIViewController {
var customview: SDKCustomView = SDKCustomView()
func CustomView(view: AnyObject!, didFailWithError error: NSError!) {
}
}
I may be wrong, but it seems in swift you can also explicitly call the init function.
Instead of calling:
var customview : CustomView = CustomView()
you can call:
var customview : CustomView = CustomView.init()
This works in my Playground, let me know how it works out for you. This would allow you to use your function named as it is.

Swift function that return two strings fail when its in loop

I Wrote a function that return two Strings, when calling the function regularly its works fine, but when I'm running the function through loop, I'm getting this error:
Thread 1: EXC_BAD_ACCESS (code=2, address=0xbfffcba0)
override func viewDidLoad()
{
super.viewDidLoad()
test()
}
func test()
{
var funcs = [checkButton]
var a = checkButton(value: 1) // Runs OK
for f in funcs{
var result = f(value: 1) // Fail
}
}
func checkButton(#value: Int) -> (location: String, pattern: String){
return ("abc","cba")
}
Update:
I'm using Xcode 6 beta 2, and running Mavericks on VMware Workstation.
Also, I've just created new clean project with that code and still getting the error.
This code runs fine for me. Your EXC_BAD_ACCESS must be coming from some other part of your code. Try setting a breakpoint and stepping through the code to find the line throwing the error.
From the “The Swift Programming Language.”
“An instance method can be called only on a specific instance of the type it belongs to. It cannot be called in isolation without an existing instance.”
checkButton() is an instance method, not a closure. It works in the first case because there is an implicit self. before checkButton(). It will not work in the second case.
If you want to make checkButton a closure you could declare it like so:
let checkButton = { (#value: Int) -> (location: String, pattern: String) in
return ("abc","cba")
}
I can confirm that it doesn't work for me either. Created a iOS single-view app from template, and added above code. crash. As an experiment, I took it out of the array (just f = self.checkButton) and got the same result.
I think it's a bug in the compiler.
First according to the book, a method is actually a function which is actually a closure, albeit one with special properties and restrictions. Shouldn't self.checkButton (or implicit version) be sufficient to "give it an existing instance", making it a closure? If MattL is correct that instance methods can't be used as closures, then the compiler shouldn't allow you to assign one to anything.
Second, the crash occurs on the exit, not on the call. And if you reference self in checkButton, (e.g. println(self.title) having previously set title), it works fine. That suggests that the instance is indeed known and operating, just something wrong on the return.
Third, changing it to a class method doesn't help. Changing these lines
var a = ViewController.checkButton(value: 1)
var funcs = [ViewController.checkButton]
class func checkButton(#value: Int) -> (location: String, pattern: String)
results in the same crash. I don't see any similar prohibition on context for class methods.
Fourth, if you simply change the return type from (location: String, pattern: String) to just String and return abc, then the whole thing works fine.
Fourth, if you wrap test and checkButton in a new class testClass, and then call it as below, it works:
class testClass {
func test()
{
var funcs = [checkButton]
var a = checkButton(value: 1) // Runs OK
for f in funcs {
var result = f(value: 1) // Fail
println(result)
}
}
func checkButton(#value: Int) -> (location: String, pattern: String){
return ("abc","cba")
}
}
class ViewController: UIViewController {
override func viewDidLoad()
{
super.viewDidLoad()
let g = testClass()
g.test()
}
}
Now change testClass to testClass: NSObject and it crashes.
So it looks like the compiler is botching up a method return when called as a closure with a tuple in a Obj-C subclass. When I put it like that, I must say that it's not terribly surprising nobody's noticed yet; you're really pushing the edge here!
More practically, in the meantime, if it's helpful, an alternative to changing your method to a closure is to keep it unchanged and just wrap it as you put it in the array:
var funcs = [{value in self.checkButton(value: value)}]
This seems to work.

Resources