I'm trying to find a way to globally set the delegate of UITextFields used in my app without having to manually do it for each and every UITextField. My initial thought was to do this using a Swift extension, but that doesn't seem to be possible. Any thoughts...?
What I have now:
extension UITextField {
var delegate : UITextFieldDelegate {
get {
return UnoccludedTextFieldDelegate.sharedInstance
}
}
}
This throws a compile error - 'delegate' used within its own type
Related
I was converting one of my swift project into SwiftUI. I need to convert delegtes and protocols to SwiftUI, is it allowed in SwiftUI? or any alternative methods are there? Please help me i'm so confused in SwiftUI.
I'm calling a delegate method from one of my class, then delegate method will be present in another ViewController.
//PresenterClass
protocol SplashPresenterDelegate {
func didFetchedSystemInfo(info: String)
}
class SplashPresenter: NSObject {
var delegate: SplashPresenterDelegate?
func getSystemInfo(){
self.delegate?.didFetchedSystemInfo(info: "ResponseString")
}
}
// Viewcontroller class
class myViewController: UIViewController {
.
.
.
}
extension myViewController: SplashPresenterDelegate{
func didFetchedSystemInfo(info: String){
print("delegate called")
}
}
Please help me to convert this code to SwiftUI
Typically, SwiftUI prefers the pattern of taking callbacks rather than protocol/delegates. For instance, each button in an ActionSheet has a closure that is executed when the button is tapped.
You shouldn't just convert your code over directly, though. SwiftUI, being declarative, uses different paradigms for a lot of things. For instance, you wouldn't have a didFetchInfo method, you would just assign it to a #Published variable.
Think about having "single sources of truth", where a single variable is always correct. For example, List simply takes an array and updates when the array changes, unlike UITableView where you provide the data through numberOfRows and cellForRowAt. I don't know enough about your specific project to give more detail, but those are things to think about.
I am working on an app where I have created modules for each feature of the app. I have to switch from one Module UI Controller to another Module UI Controller.
I have UIController in a Module and I mark that controller as Public access identifier as below
public class InterAccountTransferViewController: UIViewController {
override public func viewDidLoad() {
......
......
}
}
Above class also implements UITextField delegates in extension. When I created above class as Open access I am getting a warning on TextField delegates as below
Instance method 'textFieldDidBeginEditing' nearly matches optional
requirement 'textFieldDidBeginEditing' of protocol
'UITextFieldDelegate'
Now textfield delegates are not being called. When I tried to turn off a warning by making delegates as private, they are still not being called.
Please let me know how to silence these warnings & call the delegates as well.
Any idea or suggestion would be great. I am working on Xcode 10 with swift 4.2. Please let me know if I have to explain my question more.
With "Nearly matches", the compiler tells you two things:
It doesn't match: the method 'textFieldDidBeginEditing(_:)' is not the same as the delegate method 'textFieldDidBeginEditing(_:)'. This is in itself not a problem for the compiler, you just have a method with some name, and it doesn't know the name, so it's okay.
It very much looks like the delegate method 'textFieldDidBeginEditing(_:)'. So the compiler can see that you probably intended this to be a delegate method, and it is telling you that, well, it did not work. What you have written is not a delegate method.
It's nice from the compiler that it tells you that there is a problem. It's not so nice that it doesn't explain what the problem is exactly.
The problem is that your class has more visibility than the delegate method. Your class is public, while your delegate method is just internal (because internal is the default, if you don't have an access specifier in your declaration.)
The fix is to give the delegate method a public access specifier too.
You have to change
func textFieldDidBeginEditing(_ textField: UITextField) {
// ...
}
to
public func textFieldDidBeginEditing(_ textField: UITextField) {
// ...
}
This will let the compiler know that the method is indeed intended to be a delegate method.
Bonus Content...
How did I find the solution? I reproduced the issue in Xcode. I clicked on the warning and read the Fixup: "Make 'textFieldDidBeginEditing' non-public to silence this warning". I clicked "Fix" and the line was changed to "private func textFieldDidBeginEditing(_ textField: UITextField)". So I figured that maybe turning it public instead of private would help even more. I tried it, checked it, and it worked.
Why does Swift even do this? I'm not sure, but my guess is this: if a class is public, but the protocol method is internal, it would mean that an individual view controller object implements the protocol when you look from the perspective of the module. But since the protocol implementation is internal, the protocol method would be unavailable when looking from the perspective of outside modules, e.g. from UIKit. But this is not possible in the Objective C runtime, and even if it were possible, it would be bad. Silently making the protocol methods public or semi-public would be possible, but not very clean: e.g. one could make textFieldDidBeginEditing internal, but when you cast the object to a UITextFieldDelegate pseudo-object, you can suddenly call that method, which would also be surprising.
Try this
class InterAccountTransferViewController: UIViewController,UITextFieldDelegate {
override func viewDidLoad() {
super.viewDidLoad()
//Attach delegates
self.textfield.delegate = self
}
//TextField Delegate Method
public func textFieldDidBeginEditing(_ textField: UITextField) {
}
}
Mark your method also as public
public func textFieldDidBeginEditing(_ textField: UITextField)
Simply add public access modifier with your function like this.
public func textFieldDidBeginEditing(_ textField: UITextField) {
// do whatever you want
}
I'm trying to create a custom View which I need to focus.
According to numerous Sources this is the way to go :
override func canBecomeFocused() -> Bool {
return true
}
However after converting to Swift 3.0 this no longer works.
It throws the error:
Method does not override any method from its superclass.
If i remove the override another error gets thrown:
Method 'canbecomeFocused()' with Objective-C selector 'canBecomeFocused' conflicts with better for 'canBecomeFocused' from superclass 'UIView' with the same Objective-C Selector.
Anyway I can make a UIView Selectable for TvOS?
In Swift 3 it is change to Instance Property, so try like this.
override var canBecomeFocused: Bool {
return true
}
Check Apple Documentation on canBecomeFocused for more details.
Hi so I have a protocol called DTNavigationControllerDataSource which is defined as (leaving out the methods)
protocol DTNavigationControllerDataSource: NSObjectProtocol
Then, in my own custom UINavigationController subclass I have an instance variable of this protocol as follows.
var dataSource: DTNavigationControllerDataSource?
Basically I need to know when an object becomes the dataSource. i.e The dataSource property is set. So I can call the dataSource when it is initially set, to setup some state. I've thought about using KVO however NSObjectProtocol doesn't define any methods for doing so. I'm not sure if this is even possible or if there is an alternative way outside of using KVO to know when the dataSource property inside DTNavigationController is set. I've also tried didSet and willSet but Xcode threw errors at me, as I think that is only available for primitives.
The didSet approach should work fine actually, had no issue with the following code in a playground (Xcode 7 GM):
class DTNavigationController : UINavigationController {
var dataSource: DTNavigationControllerDataSource? {
didSet {
print("new data source: \(dataSource)")
}
}
}
In my app I have a Storyboard with a bunch of elements laid out. I am setting properties of these elements from "ViewController.swift".
On the storyboard are two UIViews, which have been subclassed to allow for drawing methods. They are to be used as "signature" fields, where a user can sign their signature into the box. This is working fine.
One of the subclassed methohds of the UIViews is "eraseBitmap" which clears the UIView of the drawing.
class SigView: UIView {
...
func eraseBitmap() {
path = nil
cache = nil
}
}
I have a button that calls a function "erase" in the parent VC.
I have tried doing
func erase() {
SigView.eraseBitmap()
}
However that generates an error saying that I'm missing an argument. eraseBitmap, however, accepts no arguments.
If I add an argument, regardless what it is, I get a "SigView not convertible to..." error.
Any ideas, or a better way of coding this part?
Your SigView class defines a method eraseBitmap() - something like:
class SigView : UIView {
func eraseBitmap () { /* ... */ }
}
You'll apply this method to instances of SigView. So, somewhere you've got an instance of SigView in your UI, like:
var aView : SigView = ...
You'll then use:
func erase () {
aView.eraseBitmap()
}
or perhaps
func erase (view:SigView) {
view.eraseBitmap()
}
The error you are getting is caused by attempting to invoke a non-class method on a class. Non-class methods can only be invoked on instances of classes.