Method 'setChecked' with Objective-C selector 'setChecked:' conflicts with setter for 'checked' with the same Objective-C selector - xcode

I have created custom class that inherits from UIButton.
In that class I have created a function defined as:
func setChecked(checked:Bool){
self.checked = checked
if checked {
buttonImageView.image = UIImage(named: "radioSelected.png")
} else {
buttonImageView.image = UIImage(named: "radioUnselected.png")
}
}
which was working fine until I updated my xCode to 6.1.3.
Now I keep getting the error message on the function definition line:
Method 'setChecked' with Objective-C selector 'setChecked:' conflicts
with setter for 'checked' with the same Objective-C selector
I already tried to make a override it but then I get a error saying that "Method does not override any method from its superclass".
Anyone know how can I correctly solve it?
(I don't want to change the name of my function.)

You have function name conflicting with your property. What about to implement it in a more elegant way with property observing? This explicitly shows how value changes, as well as a side effects for the value changes.
class RadioButton: UIButtom {
var checked: Bool = false {
didSet {
buttonImageView.image = UIImage(named: checked ? "radioSelected.png" : "radioUnselected.png")
}
}
}

It seems that there is a name collision happening. There a few more people with the same issue:
Compiler error: Method with Objective-C selector conflicts with previous declaration with the same Objective-C selector
https://stackoverflow.com/questions/30006724/method-setplayer-with-objective-c-selector-setplayer-conflicts-with-setter
Try renaming your function to something like:
func checkedSetter(checked:Bool){

Related

Swift 4.2.1 requesting JSON with Xcode 10.1

My code:
let cgpurl = URL(string: "https://api.coingecko.com/api/v3/ping")!
let task = URLSession.shared.dataTask(with: cgpurl) { (Data, URLResponse, Error) in
if let data = Data, let string = String(data: data, encoding: .utf8) {
let CGPing = string } ; resume() }
The problem is with the 2nd use of "cgpurl". I've tried changing case to no effect. The error I'm getting is, "Cannot use instance member 'cgpurl' within property initializer; property initializers run before 'self' is available". Ok... but I can't even replace cgpurl with the actual link? Then I get the error message "Ambiguous reference to member 'dataTask(with:completionHandler:)'" I realize this release of swift was supposed to be "small" & just to "fix errors" but I've not been able to find any current documentation on this release. I'm using swift 4.2.1 with Xcode 10.1
This code was taken directly from a teaching manual for Swift 4.2
No, it wasn't. The code you have was never right, in Swift 4.2 or any other version of Swift. You have blindly copied and pasted perhaps, without looking at the overall context.
The problem is that the code, as you have it, is sitting "loose" at the top of your view controller or other class declaration, perhaps something along these lines:
class MyViewController : UIViewController {
let cgpurl = // ...
let task = // ...
}
That's wrong. The most basic rule of Swift programming is that executable code can exist only in a function. For example:
class MyViewController : UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let cgpurl = // ...
let task = // ...
}
}
That may not solve all your issues, but at least you'll get past the most basic mistake you're making and the "Cannot use instance member" compile error will go away.

'#selector' refers to a method that is not exposed to Objective-C

The new Xcode 7.3 passing the parameter via addTarget usually works for me but in this case it's throwing the error in the title. Any ideas? It throws another when I try to change it to #objc
Thank you!
cell.commentButton.addTarget(self, action: #selector(FeedViewController.didTapCommentButton(_:)), forControlEvents: UIControlEvents.TouchUpInside)
The selector it's calling
func didTapCommentButton(post: Post) {
}
In my case the function of the selector was private. Once I removed the private the error was gone. Same goes for fileprivate.
In Swift 4
You will need to add #objc to the function declaration. Until swift 4 this was implicitly inferred.
You need to use the #objc attribute on didTapCommentButton(_:) to use it with #selector.
You say you did that but you got another error. My guess is that the new error is that Post is not a type that is compatible with Objective-C. You can only expose a method to Objective-C if all of its argument types, and its return type, are compatible with Objective-C.
You could fix that by making Post a subclass of NSObject, but that's not going to matter, because the argument to didTapCommentButton(_:) will not be a Post anyway. The argument to an action function is the sender of the action, and that sender will be commentButton, which is presumably a UIButton. You should declare didTapCommentButton like this:
#objc func didTapCommentButton(sender: UIButton) {
// ...
}
You'll then face the problem of getting the Post corresponding to the tapped button. There are multiple ways to get it. Here's one.
I gather (since your code says cell.commentButton) that you're setting up a table view (or a collection view). And since your cell has a non-standard property named commentButton, I assume it's a custom UITableViewCell subclass. So let's assume your cell is a PostCell declared like this:
class PostCell: UITableViewCell {
#IBOutlet var commentButton: UIButton?
var post: Post?
// other stuff...
}
Then you can walk up the view hierarchy from the button to find the PostCell, and get the post from it:
#objc func didTapCommentButton(sender: UIButton) {
var ancestor = sender.superview
while ancestor != nil && !(ancestor! is PostCell) {
ancestor = view.superview
}
guard let cell = ancestor as? PostCell,
post = cell.post
else { return }
// Do something with post here
}
Try having the selector point to a wrapper function, which in turn calls your delegate function. That worked for me.
cell.commentButton.addTarget(self, action: #selector(wrapperForDidTapCommentButton(_:)), forControlEvents: UIControlEvents.TouchUpInside)
-
func wrapperForDidTapCommentButton(post: Post) {
FeedViewController.didTapCommentButton(post)
}
As you know selector[About] says that Objective-C runtime[About] should be used. Declarations that are marked as private or fileprivate are not exposed to the Objective-C runtime by default. That is why you have two variants:
Mark your private or fileprivate method declaration by #objc[About]
Use internal, public, open method access modifier[About]

Issue between override and non-override function in swift

Sorry I'm not very good at explaining this stuff. Basically I have the function below to handle remote control events.
UIApplication.sharedApplication().beginReceivingRemoteControlEvents()
override func remoteControlReceivedWithEvent(event: UIEvent) {
if event.type == UIEventType.RemoteControl {
if event.subtype == UIEventSubtype.RemoteControlPlay {
stream.play()
} else if event.subtype == UIEventSubtype.RemoteControlPause {
stream.stop()
} else if event.subtype == UIEventSubtype.RemoteControlTogglePlayPause {
toggle()
}
}
}
Essentially, when I use the term "override" (shown above), I get the error
"Method does not override any method from its superclass.
If I leave out the "override", I get the error:
"Method 'remoteControlReceivedWithEvent' with Objective-C selector 'remoteControlReceivedWithEvent:' conflicts with method "remoteControlReceivedWithEvent" from superclass "UIResponder" with the same Objective-C selector.
I'm pretty new to all of this so I don't really understand what the issue is. Can someone please explain how to remedy this issue? Let me know if you need some more code or something.
Is there more code I have to use to set this up?
There is a mismatch of UIResponder method signature and your function implementation. UIResponder has optional Event as following:
func remoteControlReceibedWithEvent(_ event: UIEvent?)
So it can not override as there is no function with non-optional argument, but if you remove override it will conflict with ObjC implementation, as selector names are the same.

KVO working once in Swift

I'm trying to use KVO in Swift, but the method "observeValueForKeyPath" is called once.
Here's a GIST of my code
I tried to use NSNumber instead of Int, add all options to addObserver, but the method is still call once when my view load.
Any idea ?
EDIT: It seems like I found a temporary solution using:
var lifes: Int {
willSet {
willChangeValueForKey("lifes")
}
}
KVO requires dynamic dispatch, so the dynamic modifier needs to be added to the property:
dynamic var lifes = 0

Swift + Xcode 6 beta 3 + Core Data = awakeFromInsert not called?

Need help.
I'm creating new Document-based Core Data Cocoa project.
Add entity named 'Entity' into the core data model. Add 'creationDate' propery into it and set its type as Date. And create NSManagedObject subclass from 'Editor' menu.
Now I add into 'Entity.swift' file this code:
override func awakeFromInsert() {
super.awakeFromInsert()
self.creationDate = NSDate()
println("awakeFromInsert called")
}
Now in my NSPersistentDocument subclass I write such a init() method:
init() {
super.init()
var context = self.managedObjectContext
context.undoManager.disableUndoRegistration()
var entity = NSEntityDescription.insertNewObjectForEntityForName("Entity", inManagedObjectContext: context)
context.processPendingChanges()
context.undoManager.enableUndoRegistration()
println("\(entity)")
}
Everything compiles... BUT awakeFromInsert is never called! The interesting part is that 'entity' object ain't nil! It was created, but not initialized. And if I write this line in init method
entity.creationDate = NSDate()
then creationDate property will be set to a current date as expected.
But that's not all. If I debug execution step-by-step I can see that execution enters 'Entity.swift' file, but starts from the top of the file, then immediately drops and returns back to the NSPersistentDocument subclass file.
Tell me, is it a bug? Because I'm tired to fight with this nonsense. Thanks.
Accidentally I got it work: you have to add #objc(YourSubclass) before subclass declaration. I usually did #objc class MySubclass and turned out it does not work (don't know why).
WORKING:
#objc(YourSubclass)
class YourSubclass : NSManagedObject {
...
NOT WORKING:
#objc class YourSubclass : NSManagedObject {
...

Resources