Preventing protocol methods from showing up twice in autocomplete - swift

This is more of an annoyance and cosmetic issue than anything else, but there are some consistency issues with autocomplete in Xcode, and I'd very much appreciate if somebody has a solution for it.
Consider a protocol MyProtocol, which has a property and a method:
public protocol MyProtocol {
var variable: String { get }
func method()
}
And a class A which adopts MyProtocol and implements the requirements in order to conform to the protocol:
public class A { ... }
extension A: MyProtocol {
public var variable: String { get { return "String from A." } }
public func method() {
print("Method called.")
}
}
The problem:
When accessing the members of an instance of A, protocol methods show up twice, whereas properties only show up once:
If everything is documented in code, it becomes clear that the protocol properties become hidden, while protocol methods remain visible in autocomplete. The same applies for default implementations of protocol methods - still visible.
Another thing that makes this issue even more peculiar is that if an instance of e.g. A is created in the same file where the class is declared, and that instance's members are accessed within the same file as well, then the protocol method disappears from autocomplete:
But, if the same instance (which is now on the global scope) is called from another file, the protocol method reappears in autocomplete.
So, my question is: does anybody know how to hide the duplicate protocol methods from autocomplete?
Versions:
Xcode: 7.3 (7D175)
Swift: 2.2

This seems to be a bug. rdar://21701167 was filed last year.
It could be caused by:
duplicates originating from Xcode document updates
duplicates from 3rd party Xcode document plugins
installing two versions of Xcode side-by-side
It's anyone's guess really. It is sort of annoying. Sometimes I get 3 or 4 duplicates. I am using two versions of Xcode and I was using a 3rd party document plugin.

Related

Is there a way to know that method is protocol implementation in Swift?

For example, I have such a protocol
public protocol MyProtocol
{
func foo()
}
Protocol implementation
class MyClass : MyProtocol
{
public func foo() {...}
}
there is no way to know if the method foo() is a (direct) class method or protocol implementation
So, sometimes (eg:) if a certain class implements few protocols where each of them has few methods it is hard to know which method related to which protocol.
So the question is - is there actually no way to know it?
UPD
I need to know it just for a better understanding of the code and in addition, it is easier to navigate when I know which method related to which protocol.
When you are writing code, it is usually a good idea to write implementations of protocol methods in their own separate extensions. For example:
class MyClass {
// implement methods unrelated to any protocols here
}
extension MyClass : Protocol1 {
// implement the methods in Protocol1
}
extension MyClass : Protocol2 {
// implement the methods in Protocol2
}
// etc
This way you know exactly what methods belong to which protocol.
However, let's say you are reading someone else's code that you can't change.
In Xcode, you can see if a method in a class implements a protocol by holding the command key and then clicking on its name, then the "quick actions" menu comes up:
If you click on "Jump to definition",
you will be taken to the method declaration in the protocol, if the method implements a method declared in a protocol, or
you will stay where you are, if it's just a regular old method
Do note that you will also stay where you are, if the method implements a protocol method, but is overridden. So if you see an overridden method, and wants to know if it is a requirement for a protocol or not, you'll have to go to the superclass first.
Or, use AppCode, where there are markers beside these methods:
The "I" markers with a red upwards arrow are what you're looking for. Clicking on them takes you to the declaration in the protocol. For overridden methods, they look no different from regular overridden methods, and you still need to go to the superclass first by clicking on the "O" marker with a red upwards arrow.
The only downside of this is of course, you need to pay for AppCode :(

How can a Swift module/class work around the lack of language support for "protected" members?

I'm faced with a situation where I am defining a reusable base class in a module, and I want to provide certain functions that should be callable only by subclasses, not external users of that subclass.
I'm writing a framework and packaging it as a Swift module. Part of my framework includes a base class that can be subclassed to add functionality, but whereby the derived class also has a further external purpose as well. Imagine defining a new kind of view: it derives from UIView or NSView, then provides additional logic, and is then itself instantiated by another party.
In this case, I'm the one defining the UIView-like class that is intended to be subclassed, and along with it comes a lot of private UIView internal stuff, like measurement, arranging, who knows, internal stuff.
The point is, end users of this new view class don't want to see the internals of the architecture that supported the subclassing, those should be completely inside the black box of what the subclass represents.
And it strikes me that this is now impossible in Swift.
I really don't understand why Swift got rid of protected access control. According to Apple, the function that I want to expose only to subclasses "isn't really useful outside the subclass, so protection isn’t critical".
Am I missing something? Is this a whole class of design patterns that Swift simply cannot support?
One thought that occurs to me is I could perhaps split up the public-public and the private-public parts of my class into two parts, perhaps using protocols, whereby public-public users would only see the public protocol and "private" public users would see the "private" protocol as well. Alas this seems like a lot of engineering for something that used to be free.
FWIW — I've been continually asking for better access control in Swift (including protected) since before there was access control in Swift. Now, 3.5 years after we were told to give the Swift approach to access control a try, Swift has been my primary language for almost 3 of those years and I still think the access control paradigm is clumsy and unable to model concepts that are easy in almost all similar languages.
The largest mitigating factor for me is that Swift has steered me away from ever using inheritance and subclassing 95% of the time, which I think is a good thing. So this issue comes up less than it may have otherwise. But for situations exactly as you are describing, there isn't an equivalent way to accomplish what you are doing using only protocols and protocol extensions, so you are stuck either polluting a public API with possibly harmful internal details, or using some workaround (like the one that follows) which has the smallest possible public API exposure, and simulates what you want at the cost of boilerplate and awkwardness.
That said, the approach I take is somewhat inspired by Objective C, where there is also no real protected access control, but the convention is to declare a public API header (which client code will import and reference) and a special "+Subclassing" header which only subclasses will import in their implementation, giving them visibility into the not-for-public-consumption internals.
In Swift, this isn't directly possible either, but given a class like this:
open class SomeClass {
private var foo: String
private var bar: Data
public init(){
foo = "foo"
bar = Data()
}
private func doInternalThing() {
print(foo)
}
}
You can add a nested "Protected" wrapper via extension (has to be in the same file as your class declaration), which takes an instance of the class (or a subclass) and exposes the protected-level internals as a sort of proxy:
// Create a nested "Protected" type, which can accept an instance of SomeClass (or one of its subclasses) and expose the internal / protected members on it
public extension SomeClass {
public class Protected {
unowned private var someClass: SomeClass
public var foo: String {
get {
return someClass.foo
}
set {
someClass.foo = newValue
}
}
public init(_ someClass: SomeClass) {
self.someClass = someClass
}
public func doInternalThing() {
someClass.doInternalThing()
}
}
}
Outside of the framework, in the client application, the protected members are accessed in a subclass like this:
class SomeSubclass: SomeClass {
private lazy var protected: SomeClass.Protected = { SomeClass.Protected(self) }()
func doSomething() {
protected.foo = "newFoo" // Accesses the protected property foo and sets a new value "newFoo"
protected.doInternalThing() // Prints "newFoo" by calling the protected method doInternalThing which prints the foo property.
}
}
There are pros and cons for this approach. The cons are mainly the amount of boilerplate you need to write to map all your properties and functions from the Protected wrapper to the actual class instance as shown above. Also, there is no avoiding the fact that consumers will see SomeClass.Protected as a publicly visible type, but hopefully it's clear that it shouldn't be used and it's difficult enough to use it arbitrarily that it won't happen.
The pros are that there isn't a lot of boilerplate or pain for clients when creating subclasses, and its easy to declare a lazy "protected" var to get the desired API. It's pretty unlikely that non-subclass would stumble upon or use this API accidentally or unwittingly, and it's mostly hidden as desired. Instances of SomeSubclass will not show any extra protected API in code completion or to outside code at all.
I encourage anyone else who thinks access control — or really in this case, API visibility and organization — to be easier than it is in Swift today to let the Swift team know via the Swift forums, Twitter, or bugs.swift.org.
You can kinda, sorta work around it by separating out the for-subclasses stuff into a separate protocol, like this:
class Widget {
protocol SubclassStuff {
func foo()
func bar()
func baz()
}
func makeSubclassStuff() -> SubclassStuff {
// provide some kind of defaults, or throw a fatalError if this is
// an abstract superclass
}
private lazy var subclassStuff: SubclassStuff = {
return self.makeSubclassStuff()
}()
}
Then you can at least group the stuff that's not to be called in one place, to avoid it polluting the public interface any more than absolutely necessary and getting called by accident.
You can also reconsider whether you really need the subclass pattern here, and consider using a protocol instead. Unfortunately, since protocols can't nest types yet, this involves giving the subclass-specific protocol an Objective-C-style prefixed name:
protocol WidgetConcreteTypeStuff {
...
}
protocol Widget {
var concreteTypeStuff: WidgetConcreteTypeStuff { get }
}

Why can't extensions with protocol conformances have a specific access level?

Assume we have the following example code:
protocol MyProtocol {
func someFunction()
}
public class MyClass {
}
public extension MyClass: MyProtocol {
func someFunction() {
print("hello")
}
}
Compiling the code above gives the following error:
Error: 'public' modifier cannot be used with extensions that declare protocol conformances
The same thing occurs if I mark the extension as private. It seems as though you cannot set the access level of an extension that conforms to a protocol, regardless of what the access level is set to. Even setting the protocol declaration to public or private does not remove the error.
Question
What is the reasoning for Swift restricting an extension's access level in this way if it conforms to a protocol? If the protocol conformance is applied at the class level, there is no such restriction.
If I obey the compiler and remove the private/public designation, what is the access level of someFunction()?
extension MyClass: MyProtocol {
func someFunction() {
print("hello")
}
}
I imagine in this case it would follow the original MyClass implementation and be public but I am not sure.
Is this behavior there because a protocol conformance in an extension means the entire class conforms to the protocol, and therefore it is redundant to re-specify the access level in the extension?
It's because it's impossible to conform to a protocol at any access level other than the access level of the protocol itself. In other words, if you have a public protocol, you cannot have private conformance to it. This is partially because protocol conformance is something that can be queried for at runtime (and therefore cannot differ between what module you're in, or be implemented twice in different files/modules), and partially because it would just plain be weird if a type conformed to a protocol in one file and didn't conform to that protocol when used in other files.
As for your question of the access level of someFunction, it follows the same rules as any other function. Which is to say, it defaults to internal, unless the type itself has a lower access level. So in your case, if MyClass and MyProtocol are both public, you can expect to get a compiler error telling you that someFunction() needs to be marked public as well. But since it looks like MyProtocol is in fact internal, omitting any access modifier works as someFunction() defaults to internal.
Private conformance might violate Liskov Substitution Principle
Quoting an abstract from apple devloper forum reply to a similar question:
"The biggest thing I've noted about private conformance, especially amonst classes that are meant to be subclassed further, is that you often end up with conflicting implementations."
For example, you have a class that privately conforms to a protocol and implements all of its methods. Later a subclass comes along and wants to do the same, but only wants to implement the required methods (because the optional ones not being implemented might provide some default behavior that subclass wants). But now you have 2 problems:
1) The object expecting this protocol implementation now has possibly 2 consumers of the protocol on the same object. This leads to both objects having to guard against unexpected calls. Or none, as due to the private conformance, the subclass can't call super to resolve the unexpected calls.
2) There is no way for the subclass to get the behavior it wants without modifying the protocol, as the superclass's implementation can't be removed without affecting its behavior either.
Source: Link to Apple Developer forum thread
If I obey the compiler and remove the private/public designation, what is the access level of someFunction()?
Whatever you say it is. Nothing stops you from marking the access level of someFunction(). But in this case you cannot mark it as private, because the access level of MyProtocol is internal.
The default, therefore, is internal in your code. Nothing is ever public by default; public is always an explicitly opt-in designation.

Non-'#objc' method does not satisfy optional requirement of '#objc' protocol

Overview:
I have a protocol P1 which provides a default implementation of one of the Objective-C optional functions.
When I provide a default implementation of the optional function there is a warning
Compiler Warning:
Non-'#objc' method 'presentationController(_:viewControllerForAdaptivePresentationStyle:)' does not satisfy optional requirement of '#objc' protocol 'UIAdaptivePresentationControllerDelegate'
Version:
Swift: 3
Xcode: 8 (public release)
Attempts made:
Tried adding #objc but doesn't help
Question:
How do I resolved this ?
Is there a work around ?
Code:
#objc protocol P1 : UIAdaptivePresentationControllerDelegate {
}
extension P1 where Self : UIViewController {
func presentationController(_ controller: UIPresentationController, viewControllerForAdaptivePresentationStyle style: UIModalPresentationStyle) -> UIViewController? {
return UIViewController()
}
}
class A : UIViewController, P1 {
}
While I think I can answer your question, it's not an answer you will like.
TL;DR: #objc functions may not currently be in protocol extensions. You could create a base class instead, though that's not an ideal solution.
Protocol Extensions and Objective-C
First, this question/answer (Can Swift Method Defined on Extensions on Protocols Accessed in Objective-c) seems to suggest that because of the way protocol extensions are dispatched under the hood, methods declared in protocol extensions are not visible to the objc_msgSend() function, and therefore are not visible to Objective-C code. Since the method you are trying to define in your extension needs to be visible to Objective-C (so UIKit can use it), it yells at you for not including #objc, but once you do include it, it yells at you because #objc is not allowed in protocol extensions. This is probably because protocol extensions are not currently able to be visible to Objective-C.
We can also see that the error message once we add #objc states "#objc can only be used with members of classes, #objc protocols, and concrete extensions of classes." This is not a class; an extension to an #objc protocol is not the same as being in the protocol definition itself (i.e. in requirements), and the word "concrete" would suggest that a protocol extension does not count as a concrete class extension.
Workaround
Unfortunately, this pretty much completely prevents you from using protocol extensions when the default implementations must be visible to Objective-C frameworks. At first, I thought perhaps #objc was not allowed in your protocol extension because the Swift Compiler could not guarantee that conforming types would be classes (even though you have specifically specified UIViewController). So I put a class requirement on P1. This did not work.
Perhaps the only workaround is to simply use a base class instead of a protocol here, but this is obviously not completely ideal because a class may only have a single base class but conform to multiple protocols.
If you choose to go this route, please take this question (Swift 3 ObjC Optional Protocol Method Not Called in Subclass) into account. It appears that another current issue in Swift 3 is that subclasses do not automatically inherit the optional protocol requirement implementations of their superclass. The answer to that questions uses a special adaption of #objc to get around it.
Reporting the Issue
I think this is being discussed already among those working on the Swift open source projects, but you could be sure they are aware by either using Apple's Bug Reporter, which would likely eventually make its way to the Swift Core Team, or Swift's bug reporter. Either of these may find your bug too broad or already known, however. The Swift team may also consider what you are looking for to be a new language feature, in which case you should first check out the mailing lists.
Update
In December 2016, this issue was reported to the Swift community. The issue is still marked as open with a medium priority, but the following comment was added:
This is intended. There is no way to add the implementation of the method to every adopter, since the extension could be added after the conformance to the protocol. I suppose we could allow it if the extension is in the same module as the protocol, though.
Since your protocol is in the same module as your extension, however, you may be able to do this in a future version of Swift.
Update 2
In February 2017, this issue was officially closed as "Won't Do" by one of the Swift Core Team members with the following message:
This is intentional: protocol extensions cannot introduce #objc entry points due to limitations of the Objective-C runtime. If you want to add #objc entry points to NSObject, extend NSObject.
Extending NSObject or even UIViewController will not accomplish exactly what you want, but it unfortunately does not look like it will become possible.
In the (very) long-term future, we may be able to eliminate reliance on #objc methods entirely, but that time will likely not come anytime soon since Cocoa frameworks are not currently written in Swift (and cannot be until it has a stable ABI).
Update 3
As of Fall 2019, this is becoming less of a problem because more and more Apple frameworks are being written in Swift. For example, if you use SwiftUI instead of UIKit, you sidestep the problem entirely because #objc would never be necessary when referring to a SwiftUI method.
Apple frameworks written in Swift include:
SwiftUI
RealityKit
Combine
CryptoKit
One would expect this pattern to continue over time now that Swift is officially ABI and module stable as of Swift 5.0 and 5.1, respectively.
I just ran into this after enabling 'module stability' (turning on 'Build libraries for distribution') in a swift framework I use.
What I had was something like this:
class AwesomeClass: LessAwesomeClass {
...
}
extension AwesomeClass: GreatDelegate {
func niceDelegateFunc() {
}
}
The function in the extension had these errors:
'#objc' instance method in extension of subclass of 'LessAwesomeClass' requires iOS 13.0.0
Non-'#objc' method 'niceDelegateFunc' does not satisfy requirement of '#objc' protocol 'GreatDelegate'
Moving the functions into the class rather than in an extension resolved the issue.
Here's another workaround. I ran into this issue as well, and cannot switch from UIKit to SwiftUI yet. Moving the default implementations into a common base class was not an option for me either. My default implementations were quite extensive so I really did not want to have all that code duplicated. The workaround I ended up using was to use wrapper functions in the protocol, and then simply call those functions from each class. Not pretty, but may be better than the alternative, depending on the situation. Your code would then look something like this:
#objc protocol P1 : UIAdaptivePresentationControllerDelegate {
}
extension P1 where Self : UIViewController {
func wrapPresentationController(_ controller: UIPresentationController, viewControllerForAdaptivePresentationStyle style: UIModalPresentationStyle) -> UIViewController? {
return UIViewController()
}
}
class A : UIViewController, P1 {
func presentationController(_ controller: UIPresentationController, viewControllerForAdaptivePresentationStyle style: UIModalPresentationStyle) -> UIViewController? {
return wrapPresentationController(controller, viewControllerForAdaptivePresentationStyle: style)
}
}

Swift and using class extension

I don't understand why programmers use the extension keyword in their class implementation. You can read in other topics that code is then more semantically separated and etc. But when I work with my own code, it feels clearer to me to use // MARK - Something. Then when you use methods list (ctrl+6) in Xcode, everything is seen at first look.
In Apple documentation you can read:
“Extensions add new functionality to an existing class, structure, or enumeration type.”
So why not write my own code directly inside my own class? Unlike when I want to extend functionality of some foreign class, like NSURLSession or Dictionary, where you have to use extensions.
Mattt Thompson use extension in his Alamofire library, maybe he can give me little explanation, why he chose this approach.
For me it seems completely reasonable since you can use extensions to expose different parts of logic to different extensions. This can also be used to make class conformance to protocols more readable, for instance
class ViewController: UIViewController {
...
}
extension ViewController: UITableViewDelegate {
...
}
extension ViewController: UITableViewDataSource {
...
}
extension ViewController: UITextFieldDelegate {
...
}
Protocol methods are separated in different extensions for clarity, this seems to be far better to read than lets say:
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate {}
So, I'd say there's no harm in using extensions to make your own code more readable, not just to extend already existing classes from SDK. Using extensions you can avoid having huge chunks of code in your controllers and split functionality into easily readable parts, so there's no disadvantage of using those.
Using extensions allows you to keep your declaration of protocol conformance next to the methods that implement that protocol.
If there were no extensions, imagine declaring your type as:
struct Queue<T>: SequenceType, ArrayLiteralConvertible, Equatable, Printable, Deflectable, VariousOtherables {
// lotsa code...
// and here we find the implementation of ArrayLiteralConvertible
/// Create an instance containing `elements`.
init(arrayLiteral elements: T…) {
etc
}
}
Contrast this with using extensions, where you bundle together the implementation of the protocols with those specific methods that implement it:
struct Queue<T> {
// here go the basics of queue - the essential member variables,
// maybe the enqueue and dequeue methods
}
extension SequenceType {
// here go just the specifics of what you need for a sequence type
typealias Generator = GeneratorOf<T>
func generate() -> Generator {
return GeneratorOf {
// etc.
}
}
}
extension Queue: ArrayLiteralConvertible {
init(arrayLiteral elements: T...) {
// etc.
}
}
Yes, you can mark your protocol implementations with // MARK (and bear in mind, you can combine both techniques), but you would still be split across the top of the file, where the declaration of protocol support would be, and the body of the file, where your implementation is.
Also, bear in mind if you’re implementing a protocol, you will get helpful (if slightly verbose) feedback from the IDE as you go, telling you what you’ve got left to implement. Using extensions to do each protocol one by one makes it (for me) far easier than doing it all in one go (or hopping back and forth from top to bottom as you add them).
Given this, it’s then natural to group other, non-protocol but related methods into extensions as well.
I actually find it frustrating occasionally when you can’t do this. For example,
extension Queue: CollectionType {
// amongst other things, subscript get:
subscript(idx: Index) -> T {
// etc
}
}
// all MutableCollectionType adds is a subscript setter
extension Queue: MutableCollectionType {
// this is not valid - you’re redeclaring subscript(Index)
subscript(idx: Int) -> T {
// and this is not valid - you must declare
// a get when you declare a set
set(val) {
// etc
}
}
}
So you have to implement both within the same extension.