In Swift, Can You Find All Types in a Module That Adhere to a Specific Protocol

In Swift, can you find all types in a module that adhere to a specific protocol?

I don't believe Swift currently has a 'native' (not dependant on the Objective-C runtime) API for doing this kind of reflection.

However, if you're on an Apple platform (and therefore have Obj-C interoperability), you could get a list of all classes registered with the Obj-C runtime, and then filter those that conform to a given protocol. This will work for Swift classes (even those that don't inherit from NSObject) because under the hood Swift classes are built on top of Obj-C classes (when there's Obj-C interop).

Because this will only work for classes (not structures or enumerations), you may want to restrict your protocol such that only classes can conform to it:

protocol Favorite : class {}

You can then do the following, using objc_copyClassList:

import Foundation

protocol Animal {}
protocol Vehicle {}
protocol Favorite : class {}

class Dog : Animal {}
class Cat : Animal, Favorite {}
class Car : Vehicle {}
class Bicycle : Vehicle, Favorite {}

/// Invokes a given closure with a buffer containing all metaclasses known to the Obj-C
/// runtime. The buffer is only valid for the duration of the closure call.
func withAllClasses<R>(
_ body: (UnsafeBufferPointer<AnyClass>) throws -> R
) rethrows -> R {

var count: UInt32 = 0
let classListPtr = objc_copyClassList(&count)
defer {
free(UnsafeMutableRawPointer(classListPtr))
}
let classListBuffer = UnsafeBufferPointer(
start: classListPtr, count: Int(count)
)

return try body(classListBuffer)
}
// .flatMap in Swift < 4.1
let classes = withAllClasses { $0.compactMap { $0 as? Favorite.Type } }
print(classes) // [Bicycle, Cat]

Here we're calling compactMap(_:) on the UnsafeBufferPointer to get back an array of metatypes that represent types conforming to Favorite (i.e those that can be cast to the existential metatype Favorite.Type).

returning swift protocol associated type in multiple methods

The solution you came up with by playing around is exactly what you need

As mentioned elsewhere, the main issue with your first protocol is that you're enforcing createSomeView() createAnotherView() both return the same type. While ViewA() and ViewB() are both candidates for V, since they conform to View they are still different types, and therefore cannot BOTH be V in a given object.

By defining both V1 and V2, you allow for each function to return a different type, or the same type, it's all acceptable. By making both V1 and V2 require View conformance, you allow for the some View syntax

How can I execute the same function for all objects of a collection in Swift?

You can try

observers.forEach { $0.update(message: "updated") }

Xcode 13.3 build fails: Command EmitSwiftModule failed with a nonzero exit code

Problem could be with one of your libraries/pods which needs to be updated .

You could export Failed Build Logs from Xcode Report Navigator - Export Log

These Logs could be valuable to check these type of unknown build failure issues where we are not sure of what library/file is actually impacting build process.

Usually the libraries impacting the build will be found towards end of logs. In my case I had to update an Pod for which I followed below steps.

1)Run pod deintegrate

2)Inside pod file mention updated pod version or you can simply remove any explicit version which is mentioned to get latest pod version

In my case I updated pod version as " pod 'CryptoSwift', '~> 1.4.0' "

3)Run pod install.

Everything should work well after that.

*** I have attached screenshot sample of end of logs where my impacted pod was mentioned before build failure message. Hope it helps anyone ***

Sample Image

How to define a Protocol with generic function and some View as return type

This is explicitly disallowed by the Associated Type Inference section of the Opaque Result Types proposal. From the proposal:

Associated type inference can only infer an opaque result type for a non-generic requirement, because the opaque type is parameterized by the function's own generic arguments. For instance, in:

protocol P {
associatedtype A: P
func foo<T: P>(x: T) -> A
}

struct Foo: P {
func foo<T: P>(x: T) -> some P {
return x
}
}

there is no single underlying type to infer A to, because the return type of foo is allowed to change with T.

To make this more specific to your question, in order to conform to Test, there must be exactly one type that can be assigned to Result. However, your return type is generic, so it depends on the what is passed. The actual (non-opaque) return type of navigate is:

_ConditionalContent<NavigationLink<T, Text>, EmptyView>

But T is a type parameter and changes depending on how navigate is called. So there is no one type that can be assigned to Result.

You'll need something that can return a single, non-parameterized type. For the example you've given, that's probably AnyView, which is annoying.

That said, what you've written here doesn't really feel like a protocol. It looks a lot like just a function. I'd think a lot about how many different ways navigate could be written. If everyone would implement it the same way, that's just a function. (If you give another example of a conforming type, it might help to design a better approach.)

Creating Encodable class by injecting class conforming only to Encodable protocol

You cannot encode device because device must be a concrete type which conforms to Encodable. Possible solutions are an associated type of the protocol constrained to Encodable or a generic, something like

class Body<T : Encodable> : Encodable {
let device: T

init(_ deviceInfo: T) {
self.device = deviceInfo
}
}

Importing a Swift protocol in Objective-C class

You need to add the @objc attribute to your Swift protocol like so:

@objc protocol AnalyticProtocol {

}

Getting error `Do you want to add protocol stubs?

This error comes because you implemented protocol (ImageViewProtcol) but you haven't add required methods of your protocol (in your case sendImageToViewController(theImage: UIImage)). All methods of your protocol are required by default. If you want to change it, you can look here.

It's the same as when you're implementing UITableViewDataSource, you also need to add required methods like number of items etc.

To fix this, add this method to your CardsViewController:

func sendImageToViewController(theImage: UIImage) {
// do something with image
}


Related Topics



Leave a reply



Submit