In swift , super class and protocol is write together like this
Most of times ,this will not make misunderstanding , But because there is a NSObject class and a NSObject protocol with the same name, How to distinguish them?
And how the compiler know to use the NSObject class not the NSObject protocol?
And If I want to use the NSObject protocol not the NSObject class , how to write the class declaration?
The protocol is called NSObjectProtocol not NSObject which is a class. If you want something to conform to NSObjectProtocol exclusively use that:
protocol MyProtocol: NSObjectProtocol { }
On the other hand NSObject conforms to NSObjectProtocol. So in conclusion by inheriting a class from NSObject means it's refering to the NSObject class and (not the NSObject objective-c #protocol) ipso facto conforms it to NSObjectProtocol.
In Swift, NSObject protocol is imported as NSObjectProtocol so there is no naming conflict.
https://developer.apple.com/documentation/objectivec/1418956-nsobject?language=objc
Related
I want to make the existing Objective-C classes conforming to Identifiable protocol so that I could use them as list item in SwiftUI.
#interface MyClass: NSObject // What to do?
#end
For some reason, Googling doesn't help at all. Is it possible?
If not, is there a good alternative that doesn't require me to keep creating wrapper classes?
class MyClassWrapper: Identifiable {
let id = UUID()
var myClass: MyClass
}
You can use an extension to conform to Identifiable in Swift -- then just specify which property should be used as the id:
//obj-c
#interface MyClass : NSObject
#property (strong,nonatomic) NSString* myIdProperty;
#end
//Swift
extension MyClass : Identifiable {
public var id: String {
myIdProperty
}
}
I used NSString/String here, but you could use NSUUID/UUID or any other Hashable-conforming id type.
I am trying to make protocol that need to have certain type using Self == MyCustomClass. But this protocol is used as delegate type and weak constraint requires it to be also class-only protocol with ProtocolName : class
I have tried something like this
protocol MusicPlayerViewDelegate : class where Self == MusicPlayerController {
}
and then:
weak var delegate : MusicPlayerViewDelegate?
Your protocol needs to extends NSObjectProtocol to be able to use weak with it.
You can also try to make MusicPlayerController extend NSObject but I'm not sure it will work.
Basically I want to know the difference between this
protocol ViewDelegate: class {
func someFunc()
}
and this
protocol ViewDelegate: NSObjectProtocol {
func someFunc()
}
Is there any difference ??
Only Object or Instance type can conform to both type of protocol, where Structure and Enum can't conform to both the type
But the major difference is:
If one declares a protocol like below means it is inheriting NSObjectProtocol
protocol ViewDelegate: NSObjectProtocol {
func someFunc()
}
if the conforming class is not a child class of NSObject then that class need to have the NSObjectProtocol methods implementation inside it. (Generally, NSObject does conform to NSObjectProtocol)
ex:
class Test1: NSObject, ViewDelegate {
func someFunc() {
}
//no need to have NSObjectProtocol methods here as Test1 is a child class of NSObject
}
class Test2: ViewDelegate {
func someFunc() {
}
//Have to implement NSObjectProtocol methods here
}
If one declare like below, it means only object type can conform to it by implementing its methods. nothing extra.
protocol ViewDelegate: class {
func someFunc()
}
when confirming with class it means we only making in object type. So we can declare it as weak or strong
But when confirming with NSObjectProtocol, we make it object type and also we can implement NSObjectProtocol method. which is already define in NSObjectProtocol delegate.
So its up to you which way you want confirm your delegate
In some tutorials, I've seen:
class MyClass: NSObject {
var a: String!
var b: String!
init(a: String, b: String) {
super.init()
self.a = a
self.b = b
}
}
I was under the impression that swift classes didn't need to subclass anything. Is there any reason why someone would want to subclass from NSObject ?
NSObject class is not so important. What really is important is the NSObject protocol, in Swift named NSObjectProtocol.
For example, most protocols in Cocoa/CocoaTouch inherit from NSObjectProtocol. That means that if you want to use such protocols (for example, to implement delegates), you have to implement all the methods from NSObjectProtocol. That's pretty hard but NSObject class implements them all for you so the easiest solution is to inherit from NSObject class.
When you don't subclass NSObject you lose all the cool stuff Selector that comes with it: performSelector, respondsToSelector etc...
Also - this way you can make sure your Swift code objects can interact with legacy Objective-C code.
I'm trying to convert my Objective-C code to swift.
In Objective-C I have the following protocol:
#protocol RWOverlaySelectionDelegate <NSObject>
-(void)areaSelected:(UIView *)view allPoints:(NSArray *)points;
#end
and following class has a weak property that reference the protocol (obviously it's defined as weak to prevent strong reference cycle).
#interface RWMapSelectionLayer : UIView
#property(weak, nonatomic) id <RWOverlaySelectionDelegate> delegate;
#end
Now the Swift equivalent:
the protocol:
protocol RWOverlaySelectionDelegate {
func areaSelected(view:UIView,points:CGPoint[])
}
and the class that has a property which conforms to that protocol:
class RWMapSelectionLayer:NSObject {
weak var delegate:RWOverlaySelectionDelegate?
}
But I'm getting 'weak' cannot be applied to non-class type 'RWOverlaySelectionDelegate' compile time error in this line : weak var delegate:RWOverlaySelectionDelegate?
Then I tried to convert my property to an AnyObject that conforms to RWOverlaySelectionDelegate using following syntax:
weak var delegate: AnyObject<RWOverlaySelectionDelegate>?
Now I'm interfering with Generics and compiler showing: Cannot specialize non-generic type 'AnyObject' error.
In another unsuccessful try I changed it to
weak var delegate: AnyObject:RWOverlaySelectionDelegate?
read it as "Delegate is on type AnyObject where AnyObject should conform to RWOverlaySelectionDelegate"
This is again incorrect because of two colons(:) in a single statement.
Would appreciate if someone can help me to enforce conformance to a protocol on AnyObject or Any
I have since found a better way of doing this in this answer.
Updated for recent Swift versions
As I mentioned in my comment on CjCoax's answer, prefixing the protocol with #objc prevents passing Swift object types (such as enums and structs) to delegate methods.
However, using : AnyObject will allow this behaviour while allowing the protocol to be used in a weak variable, though this method is not without its limitations. You can only make classes conform to any protocol that is marked with : AnyObject. I believe that this is a better trade-off than #objc provides.
protocol MyProtocol: AnyObject {
...
}
I believe the recommended solution would be a class-only protocol. From the Swift Programming Language protocol page:
You can limit protocol adoption to class types (and not structures or enumerations) by adding the AnyObject protocol to a protocol’s inheritance list.
So in your example, your protocol definition would look like:
protocol RWOverlaySelectionDelegate: AnyObject {
func areaSelected(view: UIView, points: NSArray)
}
With the addition of the AnyObject keyword, the compiler should no longer complain.
Since swift 4 instead of class we should use AnyObject. From the Swift Programming Language protocol page:
You can limit protocol adoption to class types (and not structures or
enumerations) by adding the AnyObject protocol to a protocol’s
inheritance list.
protocol SomeClassOnlyProtocol: AnyObject, SomeInheritedProtocol {
// class-only protocol definition goes here
}
Found the solution:
I just need to declare my protocol as follow:
#objc protocol RWOverlaySelectionDelegate {
func areaSelected(view:UIView,points:NSArray)
}
and then the class just uses protocol name rather than an AnyObject that conforms to a protocol
class RWMapSelectionLayer:NSObject {
weak var delegate: RWOverlaySelectionDelegate?;
}
Protocol declaration which is #objc protocol RWOverlaySelectionDelegate require object of RWOverlaySelectionDelegate to be a class.
Here is the reference from The Swift Programing Language guide provided by apple
#objc protocols can be adopted only by classes