Function signature error (Swift 1.2) - ios

I get error after update XCode to 6.3 Function signature '(TimeInterval) -> ()' is not compatible with expected type '(value: TimeInterval) -> ()'.
Code is following:
//in `editView` property signature
var changeAction: ((value: TimeInterval)->())?
//usage
editView?.changeAction = { [unowned self] (newValue: EditDateView.TimeInterval) in
self.presentTime = newValue
wPopup?.dismiss(true)
}
Edit:
I found one solution for this:
#IBAction func timePressed() {
// some code
weak var wPopup = popup
func timeChanged(#value: EditDateView.TimeInterval) {
self.presentTime = value
wPopup?.dismiss(true)
}
editView?.changeAction = timeChanged
}
Or:
#IBAction func timePressed() {
// some code
weak var wPopup = popup
editView?.changeAction = timeChanged(wPopup)
}
func timeChanged(wPopup: KLCPopup?)(value: EditDateView.TimeInterval) {
self.presentTime = value
wPopup?.dismiss(true)
}
But this may handle self reference, not sure.

It looks like you might be confusing the type of the closure's parameter with the argument supplied to the closure upon call. It look like this assuming that TimeInterval is a valid type.
editView?.changeAction = { [unowned self] (newValue: TimeInterval) in
self.presentTime = newValue
wPopup?.dismiss(true)
}
Which you would call like this, assuming that EditDateView.TimeInterval is a valid instance of the TimeInterval type.
editView?.changeAction?(value: EditDateView.TimeInterval)

Related

Swift: Unable to set property value on mutable object paramter

I have the following code:
func enableDelaysContentTouchesIncudlingSubviews(enable: Bool) {
self.setDelaysContentTouches(enable, forObject: self)
for obj: AnyObject in self.subviews {
self.setDelaysContentTouches(enable, forObject: obj)
}
}
private func setDelaysContentTouches(var value: Bool, var forObject obj: AnyObject) {
if obj.respondsToSelector("setDelaysContentTouches:") {
obj.delaysContentTouches = value
}
}
On the second function, the line obj.delaysContentTouches = value raises the following error: Cannot assign to property: 'obj' is immutable
I don't understand the reason since obj is declared as a var parameter. Therefor it should be mutable in my understanding.
Could somebody please explain me the reason and also provide a workaround.
Thanks in advance!
My guess is it's an issue of AnyObject technically being a protocol
Assuming you're working in a view, maybe try something along these lines:
func enableDelaysContentTouchesIncudlingSubviews(enable: Bool) {
self.setDelaysContentTouches(enable, view: self)
self.subviews.forEach({setDelaysContentTouches(enable, view: $0)})
}
private func setDelaysContentTouches(enable: Bool, view: UIView) {
if let viewAsScrollview = view as? UIScrollView {
viewAsScrollview.delaysContentTouches = enable;
}
}
This is a much swiftier way of doing things, more clear, and doesn't use "respondsToSelector"
More info, and possibly a more direct answer about respondsToSelector in swift here

How to specify completion handler with one function not return [duplicate]

Error: Cannot convert the expression type (String, MyType) to ()
From the following code
Test(method: {[weak self] (message: String) in self?.callback(message)}, instance: self)
and if I add a return statement, it works, and the error goes away
Test(method: {[weak self] (message: String) in self?.callback(message); return}, instance: self)
Not sure how to handle the above without having to have the dummy return statement, any advise.
Here's my class Test
public class Test {
private var instance: AnyObject?
private var method: ((message: String) -> ())?
public init(method: (String -> ())?, instance: AnyObject) {
}
}
Edit
I've done a playground based minimalistic example (please copy paste for a test)
class Test {
private var _method: ((String) -> ())?
weak private var _instance: AnyObject?
init(method: (String -> ())?, instance: AnyObject?) {
_method = method
_instance = instance
}
}
class Another {
func register() {
//this doesn't need a return
Test(method: {(message: String) in self.callback(message)}, instance: self)
//this needs a return once I add [weak self]
Test(method: { [weak self] (message: String) in self?.callback(message); return}, instance: self)
}
func callback(message: String) {
println(message)
}
}
Not sure how to handle the above without having to have the dummy return statement, any advise.
You have solved the problem beautifully. Anonymous functions automatically use a one-line function body as a return value, so to prevent that from causing a type mismatch with the expected return type (Void) you have to add another line of code so that it is not a one-line function body. The dummy return statement, which itself returns Void, is a great way to handle it; I would just use that and move on. There are some snazzier workarounds but what you have is precisely what I would do.
EDIT: To understand the source of the type mismatch, try this:
struct Test {
func voider() -> Void {}
}
let testMaybe = Optional(Test())
let result = testMaybe?.voider()
Now result is not a Void; it's an Optional wrapping a Void. That is what's happening to you; a Void is expected but your one-line anonymous function returns an Optional wrapping a Void. By adding another line that returns Void explicitly, you solved the problem.
The implicit return is returning the result of your callback() method. That return value conflicts with the closure's return value of void. You thus need an explicit, if ugly, return.

Closure property bad access in swift (EXC_BAD_ACCESS)

I have the Test class with button_action optional closure:
class Test : CustomViewFromXib {
var button_action : (() -> ())?
#IBAction func button_pressed(sender: AnyObject) {
if let action = button_action {
action()
}
}
}
This is how I use this class:
let test_view = Test(frame: CGRect.nullRect)
self.view.addSubview(test_view)
test_view.button_action = {
() -> () in
print("test")
}
I get EXC_BAD_ACCESS error at line:
test_view.button_action = {
() -> () in
print("test")
}
I don't know why, because I just want to set initial value. Is it possible to do it that way?
UPDATE:
I understood, that no one property or method can't be called from my object. Not only closures, but Strings (for example) too.
UPDATE 2:
This is my little example of code that reproduces the problem. I think I have a problem with initializers...
https://www.dropbox.com/s/1d8fvxm0es9b5n4/TestInit.zip
(XCode 6 Beta 5)
Write code
let test_view = Test(frame: CGRect.nullRect)
self.view.addSubview(test_view)
test_view.button_action = {
() -> () in
print("test")
}
instead of
let test_view = Test(frame: CGRect.nullRect)
self.view.addSubview(test_view)
test_view.button_action = { [unowned self]
() -> () in
print("test")
}
Here is exact detail theoretical answer
Shall we always use [unowned self] inside closure in Swift
https://developer.apple.com/library/prerelease/mac/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html

How to Correctly handle Weak Self in Swift Blocks with Arguments

In my TextViewTableViewCell, I have a variable to keep track of a block and a configure method where the block is passed in and assigned.
Here is my TextViewTableViewCell class:
//
// TextViewTableViewCell.swift
//
import UIKit
class TextViewTableViewCell: UITableViewCell, UITextViewDelegate {
#IBOutlet var textView : UITextView
var onTextViewEditClosure : ((text : String) -> Void)?
func configure(#text: String?, onTextEdit : ((text : String) -> Void)) {
onTextViewEditClosure = onTextEdit
textView.delegate = self
textView.text = text
}
// #pragma mark - Text View Delegate
func textViewDidEndEditing(textView: UITextView!) {
if onTextViewEditClosure {
onTextViewEditClosure!(text: textView.text)
}
}
}
When I use the configure method in my cellForRowAtIndexPath method, how do I properly use weak self in the block that I pass in.
Here is what I have without the weak self:
let myCell = tableView.dequeueReusableCellWithIdentifier(textViewCellIdenfitier) as TextViewTableViewCell
myCell.configure(text: body, onTextEdit: {(text: String) in
// THIS SELF NEEDS TO BE WEAK
self.body = text
})
cell = bodyCell
UPDATE: I got the following to work using [weak self]:
let myCell = tableView.dequeueReusableCellWithIdentifier(textViewCellIdenfitier) as TextViewTableViewCell
myCell.configure(text: body, onTextEdit: {[weak self] (text: String) in
if let strongSelf = self {
strongSelf.body = text
}
})
cell = myCell
When I do [unowned self] instead of [weak self] and take out the if statement, the app crashes. Any ideas on how this should work with [unowned self]?
If self could be nil in the closure use [weak self].
If self will never be nil in the closure use [unowned self].
If it's crashing when you use [unowned self] I would guess that self is nil at some point in that closure, which is why you had to go with [weak self] instead.
I really liked the whole section from the manual on using strong, weak, and unowned in closures:
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html
Note: I used the term closure instead of block which is the newer Swift term:
Difference between block (Objective C) and closure (Swift) in ios
**EDITED for Swift 4.2:
As #Koen commented, swift 4.2 allows:
guard let self = self else {
return // Could not get a strong reference for self :`(
}
// Now self is a strong reference
self.doSomething()
P.S.: Since I am having some up-votes, I would like to recommend the reading about escaping closures.
EDITED: As #tim-vermeulen has commented, Chris Lattner said on Fri Jan 22 19:51:29 CST 2016, this trick should not be used on self, so please don't use it. Check the non escaping closures info and the capture list answer from #gbk.**
For those who use [weak self] in capture list, note that self could be nil, so the first thing I do is check that with a guard statement
guard let `self` = self else {
return
}
self.doSomething()
If you are wondering what the quote marks are around self is a pro trick to use self inside the closure without needing to change the name to this, weakSelf or whatever.
EDIT: Reference to an updated solution by LightMan
See LightMan's solution. Until now I was using:
input.action = { [weak self] value in
guard let this = self else { return }
this.someCall(value) // 'this' isn't nil
}
Or:
input.action = { [weak self] value in
self?.someCall(value) // call is done if self isn't nil
}
Usually you don't need to specify the parameter type if it's inferred.
You can omit the parameter altogether if there is none or if you refer to it as $0 in the closure:
input.action = { [weak self] in
self?.someCall($0) // call is done if self isn't nil
}
Just for completeness; if you're passing the closure to a function and the parameter is not #escaping, you don't need a weak self:
[1,2,3,4,5].forEach { self.someCall($0) }
Put [unowned self] before (text: String)... in your closure. This is called a capture list and places ownership instructions on symbols captured in the closure.
Use Capture list
Defining a Capture List
Each item in a capture list is a pairing of the weak or unowned
keyword with a reference to a class instance (such as self) or a
variable initialized with some value (such as delegate =
self.delegate!). These pairings are written within a pair of square
braces, separated by commas.
Place the capture list before a closure’s parameter list and return
type if they are provided:
lazy var someClosure: (Int, String) -> String = {
[unowned self, weak delegate = self.delegate!] (index: Int, stringToProcess: String) -> String in
// closure body goes here
}
If a closure does not specify a parameter list or return type because
they can be inferred from
context, place the capture list at the very start of the closure,
followed by the in keyword:
lazy var someClosure: Void -> String = {
[unowned self, weak delegate = self.delegate!] in
// closure body goes here
}
additional explanations
As of swift 4.2 🔸 we can do:
_ = { [weak self] value in
guard let self = self else { return }
print(self) //👈 will never be nil
}()
Swift 4.2
let closure = { [weak self] (_ parameter:Int) in
guard let self = self else { return }
self.method(parameter)
}
https://github.com/apple/swift-evolution/blob/master/proposals/0079-upgrade-self-from-weak-to-strong.md
You can use [weak self] or [unowned self] in the capture list prior to your parameters of the block. The capture list is optional syntax.
[unowned self] works good here because the cell will never be nil. Otherwise you can use [weak self]
From Swift 5.3, you do not have to unwrap self in closure if you pass [self] before in in closure.
Refer someFunctionWithEscapingClosure { [self] in x = 100 } in this swift doc
If you are crashing than you probably need [weak self]
My guess is that the block you are creating is somehow still wired up.
Create a prepareForReuse and try clearing the onTextViewEditClosure block inside that.
func prepareForResuse() {
onTextViewEditClosure = nil
textView.delegate = nil
}
See if that prevents the crash. (It's just a guess).
[Closure and strong reference cycles]
As you know Swift's closure can capture the instance. It means that you are able to use self inside a closure. Especially escaping closure[About] can create a strong reference cycle[About]. By the way you have to explicitly use self inside escaping closure.
Swift closure has Capture List feature which allows you to avoid such situation and break a reference cycle because do not have a strong reference to captured instance. Capture List element is a pair of weak/unowned and a reference to class or variable.
For example
class A {
private var completionHandler: (() -> Void)!
private var completionHandler2: ((String) -> Bool)!
func nonescapingClosure(completionHandler: () -> Void) {
print("Hello World")
}
func escapingClosure(completionHandler: #escaping () -> Void) {
self.completionHandler = completionHandler
}
func escapingClosureWithPArameter(completionHandler: #escaping (String) -> Bool) {
self.completionHandler2 = completionHandler
}
}
class B {
var variable = "Var"
func foo() {
let a = A()
//nonescapingClosure
a.nonescapingClosure {
variable = "nonescapingClosure"
}
//escapingClosure
//strong reference cycle
a.escapingClosure {
self.variable = "escapingClosure"
}
//Capture List - [weak self]
a.escapingClosure {[weak self] in
self?.variable = "escapingClosure"
}
//Capture List - [unowned self]
a.escapingClosure {[unowned self] in
self.variable = "escapingClosure"
}
//escapingClosureWithPArameter
a.escapingClosureWithPArameter { [weak self] (str) -> Bool in
self?.variable = "escapingClosureWithPArameter"
return true
}
}
}
weak - more preferable, use it when it is possible
unowned - use it when you are sure that lifetime of instance owner is bigger than closure
[weak vs unowned]

Swift: could not find an overload for conversion that accepts supplied argument

If I set the argument to nil, the error appears. The code like this:
func addChild(childToAdd: UIViewController, childToRemove: UIViewController) {
if (childToRemove != nil) {
childToRemove.view.removeFromSuperview()
}
var frame = childToAdd.view.frame as CGRect
frame.size.width = view.frame.size.width;
frame.size.height = view.frame.size.height;
childToAdd.view.frame = frame
view.addSubview(childToAdd.view)
}
override func viewDidLoad() {
super.viewDidLoad()
addChild(firstViewController, childToRemove: nil) //could not find an overload for conversion that accepts supplied argument
}
As you can see, I should not put nil in there, but what should I put into. It's working in Objective-c.
Your childToRemove parameter is defined as a UIViewController, which is not an optional so cannot be nil
try :
func addChild(childToAdd: UIViewController, childToRemove: UIViewController?) {
to allow nil value for you second parameter, and don't forget you need to unwrap your optional before using it (using if let is a great way to do so) :
if let childController = childToRemove {
childController.view.removeFromSuperview()
}
briefly, you second parameter should be optional, if you'd like to send nil:
func addChild(childToAdd: UIViewController, childToRemove: UIViewController?) {
if childToRemove != nil {
childToRemove!.view.removeFromSuperview()
}
// the rest is the same...
}

Resources