Error in conformance of protocol to a class : Redundant conformance of "AnyClass" to protocol Equatable [duplicate] - xcode

I updated my project to Swift 2, and received a bunch of redundant conformance of XXX to protocol YYY. This happens especially often (or always) when a class conforms to CustomStringConvertible. Also some place with Equatable.
class GraphFeatureNumbersetRange: GraphFeature, CustomStringConvertible { // <--- get the error here
...
}
I suspect that I don't need to explicitly conform to a protocol when I implement var description: String { get }, or whatever methods the protocol requires. Should I just follow fixit instructions and remove all these? Does Swift now automatically infer the conformance if a class implements all the protocol's methods?

You'll get that error message in Xcode 7 (Swift 2) if a subclass declares conformance
to a protocol which is already inherited from a superclass. Example:
class MyClass : CustomStringConvertible {
var description: String { return "MyClass" }
}
class Subclass : MyClass, CustomStringConvertible {
override var description: String { return "Subclass" }
}
The error log shows:
main.swift:10:27: error: redundant conformance of 'Subclass' to protocol 'CustomStringConvertible'
class Subclass : MyClass, CustomStringConvertible {
^
main.swift:10:7: note: 'Subclass' inherits conformance to protocol 'CustomStringConvertible' from superclass here
class Subclass : MyClass, CustomStringConvertible {
^
Removing the protocol conformance from the subclass declaration
solves the problem:
class Subclass : MyClass {
override var description: String { return "Subclass" }
}
But the superclass must declare the conformance explicitly, it is
not automatically inferred from the existence of the description
property.

For googlers, I also got this error when including SwiftyJson in my Tests target and adding a swift test class, as it caused SwiftyJson to be compiled in again, and it declares NSNumber as Comparable. The solution was to only include it in the app target.

The point is that your GraphFeatureNumbersetRange is NSObject's subclass.
Which in its turn already conforms to CustomStringConvertible! That's it! Just delete this redundant protocol. Now you're declaring it twice! :-)

Related

Protocols with associated types in Swift 4.2

I have a question about protocols with associated types, that occurred after updating to Xcode 10 and Swift 4.2.
Before I had a protocol:
protocol ViewModelBased: class {
associatedtype ViewModel
var viewModel: ViewModel { get set }
}
and a VC implementing it.
class MyViewController: UIViewController, ViewModelBased {
var viewModel: EntitiesViewModel!
}
After update to Xcode 10 I get and error saying MyViewController doesn't conform to the protocol and I have to declare the property as:
var viewModel: ViewModel! { get set }
Anyone has any idea why there is difference as I don't get it?
Basically your code was always dubious and now you’ve been caught:
protocol ViewModelBased: class {
associatedtype ViewModel
var viewModel: ViewModel { get set }
}
class MyViewController: UIViewController, ViewModelBased {
var viewModel: EntitiesViewModel!
}
In the protocol adopter MyViewController, what type do you claim corresponds to ViewModel? It seems you think it should be EntitiesViewModel. And the compiler permitted this to slide, allowing the implicitly unwrapped Optional wrapping a type to be substituted for the type itself.
But now there is no implicitly unwrapped Optional type; the type EntitiesViewModel! is effectively the same as the type EntitiesViewModel?, an Optional wrapping EntitiesViewModel. So if you want EntitiesViewModel to be ViewModel, and if you want this property’s type to be an Optional wrapping EntitiesViewModel, the protocol must declare this property’s type as an Optional wrapping ViewModel.

Redundant conformance error message Swift 2

I updated my project to Swift 2, and received a bunch of redundant conformance of XXX to protocol YYY. This happens especially often (or always) when a class conforms to CustomStringConvertible. Also some place with Equatable.
class GraphFeatureNumbersetRange: GraphFeature, CustomStringConvertible { // <--- get the error here
...
}
I suspect that I don't need to explicitly conform to a protocol when I implement var description: String { get }, or whatever methods the protocol requires. Should I just follow fixit instructions and remove all these? Does Swift now automatically infer the conformance if a class implements all the protocol's methods?
You'll get that error message in Xcode 7 (Swift 2) if a subclass declares conformance
to a protocol which is already inherited from a superclass. Example:
class MyClass : CustomStringConvertible {
var description: String { return "MyClass" }
}
class Subclass : MyClass, CustomStringConvertible {
override var description: String { return "Subclass" }
}
The error log shows:
main.swift:10:27: error: redundant conformance of 'Subclass' to protocol 'CustomStringConvertible'
class Subclass : MyClass, CustomStringConvertible {
^
main.swift:10:7: note: 'Subclass' inherits conformance to protocol 'CustomStringConvertible' from superclass here
class Subclass : MyClass, CustomStringConvertible {
^
Removing the protocol conformance from the subclass declaration
solves the problem:
class Subclass : MyClass {
override var description: String { return "Subclass" }
}
But the superclass must declare the conformance explicitly, it is
not automatically inferred from the existence of the description
property.
For googlers, I also got this error when including SwiftyJson in my Tests target and adding a swift test class, as it caused SwiftyJson to be compiled in again, and it declares NSNumber as Comparable. The solution was to only include it in the app target.
The point is that your GraphFeatureNumbersetRange is NSObject's subclass.
Which in its turn already conforms to CustomStringConvertible! That's it! Just delete this redundant protocol. Now you're declaring it twice! :-)

Custom NSValueTransformer in xcode 6 with swift

Did anyone successfully implement a custom NSValueTransformer in xcode 6 beta with swift?
I have the following swift class:
import Foundation
class myTransformer: NSValueTransformer {
let amount = 100
override class func transformedValueClass() -> AnyClass!
{
return NSNumber.self
}
override func transformedValue(value: AnyObject!) -> AnyObject! {
return value.integerValue + amount
}
}
So all this transformer should do is, adding 100 to a given value in the gui.
As you can see, the transformer class appears now in the Value Transformer drop down in IB.
But if I choose this transformer the application crashes with:
2014-08-27 20:12:17.686 cdTest[44134:303]
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException',
reason: 'Cannot find value transformer with name newTransformer'
Is it right to register this transformer in the AppDelegate with
override class func initialize() {
let newTransformer = myTransformer()
}
Does anyone know how this whole stuff should work?
kind regards!
martin
From Xcode release notes:
If you set a Swift subclass of NSValueTransformer as a binding’s value
transformer, the XIB or storyboard will contain an invalid reference
to the class, and the binding will not work properly at runtime. You
can either enter a mangled class name into the Value Transformer field
or add the #objc(…) attribute to the NSValueTransformer subclass to
solve this problem. (17495784)
From Swift guide:
To make your Swift class accessible and usable back in Objective-C,
make it a descendant of an Objective-C class or mark it with the #objc
attribute. To specify a particular name for the class to use in
Objective-C, mark it with #objc(<#name#>), where <#name#> is the name
that your Objective-C code will use to reference the Swift class. For
more information on #objc, see Swift Type Compatibility.
Solution:
Declare your class as #objc(myTransformer) class myTransformer: NSValueTransformer and then you can use "myTransformer" as name...
After you initialise newTransformer you should also include the line:
NSValueTransformer.setValueTransformer(newTransformer, forName: "myTransformer")
Then in your Interface Builder you should use myTransformer instead of newTransformer under the Value Transformer dropdown.

How to initialize a NSWindowController in Swift?

I want to initialize a window controller object from a nib file, quite easy right? But I simply can't get it to work.
According to my previous experience in ObjC, I've written down the following code:
init() {
super.init(windowNibName: "SplitWindowController")
}
And in the app delegate file, I simply init and displays the window:
var myWindowController: MyWindowController = MyWindowController()
myWindowController.showWindow(self)
myWindowController.window.makeKeyAndOrderFront(nil)
But the compiler gives me this error: Must call a designated initializer of the superclass 'NSWindowController'. And according to the Swift version of NSWindowController definition, there are only 3 designated initializers, namely init(), init(window), init(coder). I don't know what to do next. Shall I build a NSCoder from a nib file, which I don't know how to do?
You were almost there. You can indeed override init() as a convenience initialiser in a manner that is equivalent to the Obj-C code you got used to:
import Cocoa
class MyWindowController: NSWindowController {
override convenience init() {
self.init(windowNibName: "<xib name>")
}
}
Note that you are calling init(windowNibName:) on self, because init() being a convenience initialiser, you still inherit all the initialisers from the superclass. From documentation:
Rule 1: A designated initializer must call a designated initializer
from its immediate superclass.
Rule 2: A convenience initializer must call another initializer from
the same class.
Rule 3: A convenience initializer must ultimately call a designated
initializer.
Also, as #weichsel mentioned above, make sure you set the class of the File's Owner to your subclass of NSWindowController (in the example above, that would be MyWindowController) and then connect its window outlet with the window itself.
That being said, I'm not sure why is compiler asking for the override keyword to be added. Though NSWindowController is a subclass of NSResponder, which defines an init(), the following code compiles without issue even though it implements an equivalent inheritance hierarchy:
class A {
init() { }
}
class B: A {
init(Int) {
super.init()
}
convenience init(String) {
self.init(5)
}
}
class C: B {
convenience init() {
self.init("5")
}
}
NSWindowController has 2 designated initializers:
init(window: NSWindow!)
init(coder: NSCoder!)
When creating a subclass, you should invoke the designated initializer of its superclass. Recent versions of Xcode enforce this. Either via built-in language mechanism (Swift) or via NS_DESIGNATED_INITIALIZER macro (Objective-C).
Swift additionally requires that you call the superclasses designated initializer when you override a convenience initializer.
From the "Initialization: Designated Initializers and Convenience Initializers" section of Swift Programming Guide:
If the initializer you are overriding is a convenience initializer,
your override must call another designated initializer from its own
subclass, as per the rules described above in Initializer Chaining.
In your case, you should probably override init(window: NSWindow!) and call super's counterpart from there.

Obj-C Private Method Compiler Warnings

Private methods are a useful construct to keep code organised within class boundaries. An example being the organisation of long winded Quartz 2d instructions in a custom UIView subclass. I am able to include such methods in '.m' files with no declaration in '.h'. A working example from a UIView subclass '.m' file reads:
-(void)DoSomethingPrivate { //Not declared in interface
NSLog(#"Does this print a private function?");
}
- (id)initWithFrame:(CGRect)frame //Declared in inherited interface
{
self = [super initWithFrame:frame];
if (self) {
[self DoSomethingPrivate]; //Error: 'Instance method not found'
} //... but it works anyway.
return self;
}
My problem is that the compiler generates the warning "Instance method '-DoSomethingPrivate' not found (return type defaults to 'id')" on the line calling the private function. I'm aware from responses to this question that I can use a 'no name' interface category to 'hide' private method declarations.
However, when I review Apple sample code SimpleStocks, file "SimpleStockView.m", it contains a private function which is neither declared in a no-name category interface, nor does it generate compiler warnings:
//Private Function
- (void)drawRadialGradientInSize:(CGSize)size centeredAt:(CGPoint)center {
...
}
//Is called by this function...
- (UIImage *)patternImageOfSize:(CGSize)size {
...
//The next line doesn't generate any warnings!
[self drawRadialGradientInSize:size centeredAt:center];
...
}
I'd be grateful if anyone can shed any light on how Apple's sample-code private-methods appear to escape compiler checks, so I may avoid having to maintain a 'no-name' category header with all my private methods.
Many thanks.

Resources