Objective-C selector deprecated replacement
why deprecate more dynamic method?
From the proposal to make this change:
we free the developer from having to do the naming translation manually and get static checking that the method exists and is exposed to Objective-C.
For your approach, you could make a protocol that indicates a certain method is present:
@objc protocol MenuButtonClickable {
func menuButtonClicked()
}
In your view controller, add this method:
extension MyViewController : MenuButtonClickable {
func menuButtonClicked() {
// do something
}
}
Then update your method signature to use this protocol:
static func createMenuButton(controller:MenuButtonClickable) -> UIBarButtonItem {
Now the Swift compiler is guaranteed that controller
has that method, so you'll be able to use the new #selector
syntax.
And if you accidentally try to use this method on a view controller without this function, you'll get a compile-time error instead of a runtime error.
Port method swizzle of NSLocale.currentLocale from swift 2.3 to swift 3
current
is a (read-only) computed property of NSLocale
:
open class var current: Locale { get }
You build a selector for Objectice-C property getter with
let originalSelector = #selector(getter: NSLocale.current)
See also SE-0064 Referencing the Objective-C selector of property getters and setters.
How do i get the button value in swift 4?
You have several issues. To fix the crash, replace Selector(("pressed:"))
with #selector(pressed)
. The use of Selector
is very out-of-date. Always use #selector
.
Next, remove the @IBOutlet var button: UIButton!
line. You don't need it.
Then change:
button = UIButton.init(type: UIButtonType.custom) as UIButton
to:
let button = UIButton(type: .custom)
Then update your pressed
function to:
@objc func pressed(sender: UIButton){
let buttonTitle = sender.currentTitle
print(buttonTitle)
}
Note the addition of @objc
. This is required for any function being used with a target/selector. Also note that sender
is now UIButton
instead of Any
. It's best to set the sender's type to match the proper type.
Here's all of your code with lots of little fixes:
func randomize() {
var xAxis: CGFloat = 8.0
var yAxis: CGFloat = 330.0
for selectedSynonym in selectedSynonyms {
let button = UIButton(type: .custom)
button.frame = CGRect(x: xAxis, y: yAxis, width: 400, height: 50)
button.backgroundColor = .black
button.setTitle(selectedSynonym, for: .normal)
button.setTitleColor(.white, for: .normal)
button.addTarget(self, action: #selector(pressed), for: .touchUpInside)
self.view.addSubview(button)
xAxis = 10.0
yAxis += 70.0
}
}
@objc func pressed(sender: UIButton){
let buttonTitle = sender.currentTitle
print(buttonTitle)
}
Use camelCase, not snake_case when naming variables and functions. Make use of Swift type inference.
Swift: unrecognised selector sent to instance both with/without delegate
I would split it into two stages.
Link the button to a selector in the child view controller (the following is Swift 2.3 syntax) along the following lines:
button.addTarget(self, action #selector(self.buttonTapped()), forControlEvents: UIControlEvents.touchUpInside)
Then call the delegate method from within your implementation of buttonTapped(_:):
func buttonTapped() -> Void {
Self.delegate.buttonWasTapped()
...
}
[Incidentally, check also that the delegate is not nil. You've declared it as an implicitly unwrapped optional which is correct, but this means you need to set the delegate from the parent view controller.]
Swift - scheduledTimerWithTimeInterval - NSInvocation
Beginning with iOS 10 and Swift 3, it is possible to use (NS)Timer with a block closure and thus avoid Objective-C selector invocation when the timer fires:
if #available(iOS 10.0, *) {
Timer.scheduledTimer(withTimeInterval: 1.0, repeats: false, block: { (Timer) in
self.connect() // per the OP's example
})
}
In addition to avoiding the @objc
decorator, using this technique allows you to invoke methods that include non-Objective-C-compatible parameter types such as enums and optionals.
Re: setTimeout(this.connect, 1)
from the Javascript, if you don't need to cancel it, a more direct analogy in Swift 3 might be:
DispatchQueue.Main.asyncAfter(deadline: .now() + 1.0, execute { self.connect() })
Which is pretty darn close given that you actually have a choice of which thread to run on ;-)
NSNotificationCenter addObserver in Swift
It's the same as the Objective-C API, but uses Swift's syntax.
Swift 4.2 & Swift 5:
NotificationCenter.default.addObserver(
self,
selector: #selector(self.batteryLevelChanged),
name: UIDevice.batteryLevelDidChangeNotification,
object: nil)
If your observer does not inherit from an Objective-C object, you must prefix your method with @objc
in order to use it as a selector.
@objc private func batteryLevelChanged(notification: NSNotification){
//do stuff using the userInfo property of the notification object
}
See NSNotificationCenter Class Reference, Interacting with Objective-C APIs
How to make a time picker view in swift 3.0?
Set the datePickerMode
to time
Swift 3
self.datePicker.datePickerMode = .time
Swift 2.3 or lower
self.datePicker.datePickerMode = .Time
Note: This will allow you to only select Hours
and Minutes
, if you want to select Seconds
also you need to go for custom time picker.
Related Topics
Same Class Extension in Two Different Modules
How to Release a Cgdataprovider in Swift on iOS
Limit Textfield to X Amount of Characters Using Swiftui
How to Add Icon to a Share Sheet in Swift
How to Refresh Multiple Timers in Widget iOS14
Disable Https Get Certificate Check in Swift 5
How to Rotate an Object Around Only One Axis in Realitykit
JSONencoder Won't Allow Type Encoded to Primitive Value
Encoding Swift String as Escaped Unicode
Correct Way to Use Nwconnection for Long-Running Tcp Socket
Characters Is Unavailable' Please Use String Directly
Scenekit Shape Between 4 Points
Display Table View When Searchbar (From Searchcontroller) Begin Edited Swift
Overriding Static Vars in Subclasses Swift 1.2