I am using Swinject in my Swift 3 app. When I tried
let container = Container()
container.register(NetworkModeling.self) { _ in Network() }
I get an error saying
Ambiguous reference to member 'register(_:name:factory:)'
What is wrong here?
I faced the same issue and i think compiler could be a bit more verbose in this case.
Anyway, my problem was on my side, not in Swinject
Check the following:
NetworkModeling and Network are visible in scope of your registration (they are public, or internal in the same module. remember, that swift3 introduced fileprivate and many other specifiers, so make sure your identifiers are visible to registeting code
Make sure that Network conforms to NetworkModeling. Being unable to see inheritance, swift compiler raises error about ambigous types for Swinject factory
Hope, this helps
Related
I am new to swift and am trying to build an app. I am receiving "Expected Declaration" error on Xcode when I type the following code.
.edgesIgnoringSafeArea(.bottom)
Please guide me on how to resolve it. Thanks
A declaration is one of the things listed in https://docs.swift.org/swift-book/ReferenceManual/Declarations.html
If the compiler is saying it's expecting a declaration, it means you have written something that isn't a declaration in some place in the code where only a declaration is allowed.
In your case .edgesIgnoringSafeArea is a method on SwiftUI View type, so it would only be valid to put that right after a SwiftUI view, not on its own. It might be because you have brackets in the wrong place.
I have updated my Xcode to 12.5. And now I can see next warning:
"Redundant constraint 'Self' : 'AnyObject'"
What does cause this warning?
(RouterType has to be available only for classes.)
AnyObject requires the member that conforms to the protocol to be a class, but you already marked it #objc, and in Objective-C only classes can conform to protocols.
Thus requiring AnyObject is redundant and you can remove it.
The reasoning behind this warning is flawed, in my view. The terms are not synonyms.
AnyObject makes this a class protocol.
#objc exposes the protocol to Objective-C.
That’s two different things. The latter may logically imply the former, in that only a class protocol can be exposed to Objective-C; but that doesn’t make it redundant. (The type declaration in let s : String = "x" is redundant logically, after all, in just the same way — the compiler doesn’t need it — but there’s no warning.)
Apple has made a wrong decision here. I intend to file a bug.
Let's say that we have the following Objective-C API:
- (id)foo:(Protocol *)proto;
Which is imported into Swift as:
func foo(_ proto: Protocol) -> Any
Yep, it's one of those things that gives us a proxy object. These tend to be annoying to use in Swift, so let's say we want to make a wrapper around this thing to make it a bit friendlier. First we define a couple of Objective-C-compatible protocols:
#objc protocol Super {}
#objc protocol Sub: Super {}
Now, we define a function that takes a protocol conforming to Super and passes it along to foo(), and then we call it with Sub as the parameter to see if it works:
func bar<P: Super>(proto: P.Type) {
let proxy = foo(proto)
// do whatever with the proxy
}
bar(proto: Sub.self)
Well, this doesn't compile. The error message given is:
error: cannot convert value of type 'P.Type' to expected argument type 'Protocol'
Here's some stuff that does (mostly) compile:
func bar<P: Super>(proto: P.Type) {
// when called with 'Sub.self' as 'proto':
print(type(of: proto)) // Sub.Protocol
print(type(of: Sub.self)) // Sub.Protocol
print(proto == Sub.self) // true
let proxy1 = foo(Sub.self) // compiles, runs, works
let proxy2 = foo(proto) // error: cannot convert value of type 'P.Type' to expected argument type 'Protocol'
}
Okay, it's the same as Sub.self in almost every way except that I can't pass it to something requiring an Objective-C protocol. Hmm.
The problem is that, although the fact that Sub conforms to Super means that it must be an Objective-C protocol, the compiler isn't realizing this. Can we work around that and get it bridged manually? Well, let's take a look at Protocol's interface, to see if there's anything that we can...
OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0)
#interface Protocol : NSObject
#end
Oh. Hrm.
Well, the fact that Protocol is a full-fledged NSObject subclass suggests that this is all probably the work of my bestest favoritest feature, the magical Swift<->Objective-C bridge that performs non-trivial conversions on things without it being obvious what is going on. Well, this gives me an idea, at least; I should be able to manually invoke the bridge by casting to AnyObject and hopefully get at the Protocol object that way maybe by as!ing it or something. Does it work?
print(Sub.self as AnyObject) // <Protocol: 0x012345678>
Well, that's promising. And when I try it on my generic parameter?
print(proto as AnyObject) // Terminated due to signal: SEGMENTATION FAULT (11)
Oh, come on.
I suspect this is probably a bug in the compiler, and I plan to test a few things to determine whether that's the case, but since the Swift sources take a geologic age to compile, I figured I'd post this here while I'm waiting. Anyone have any insight and/or workarounds on what is going on here?
I know it's not pretty and "Swifty", exactly, but getting the Objective-C Protocol as appropriate for passing into foo can be achieved using NSProtocolFromString as follows:
let proxy2 = foo(NSProtocolFromString(String(reflecting: proto))!)
where String(reflecting:) is a useful way to get the fully qualified type name suitable for resolving via NSProtocolFromString.
I'd say the crash you encountered is a bug.
Okay, after investigating this a bit more, I've determined that it is indeed a compiler bug, and have filed a report on it: SR-8129. What appears to be happening is that the Swift compiler falsely assumes that proto will always be a metatype of a concrete class type, so it performs the bridging by emitting a call to swift_getObjCClassFromMetadata, which crashes when it encounters the protocol metatype. When Sub.self is explicitly cast to AnyObject, the compiler emits Swift._bridgeAnythingToObjectiveC<A>(A) -> Swift.AnyObject instead, which appears to dynamically determine the type of the object and bridge it accordingly.
With this in mind, the workaround becomes apparent: cast proto to Any first, to destroy the type information associated with the generic and force the compiler to emit Swift._bridgeAnythingToObjectiveC<A>(A) -> Swift.AnyObject. And indeed, this appears to work:
func bar<P: Super>(proto: P.Type) {
foo(proto as Any as AnyObject as! Protocol)
}
Not the prettiest thing out there, but probably preferable to looking up the protocol via string manipulation.
I'm using the new Swift 4 KVO and KeyPath APIs to observe changes on an object. Specifically I'm trying to observe something on the selection object of an NSArrayController. The problem is the selection is of type Any and that seems to be at odds with generating the required keypath, since the compiler doesn't know of any properties on an object of type Any.
The property's name is assetPointHeight. And my code looks like this:
var observation: NSKeyValueObservation?
observation = arrayController.observe(
#keyPath(NSArrayController.selection.assetPointHeight),
options: [.new],
changeHandler: { [weak self] (_, _) in
self?.updateLabel()
}
)
I get two compile errors:
Generic parameter Value could not be inferred
Type 'Any' has no member 'assetPointHeight'
How can I achieve what I'm looking for here? Is there another way of generating this KeyPath?
I would not expect this to work because assetPointHeight isn’t a real property on selection (eg, it’s not defined anywhere in source code, it’s a virtual property created at runtime). I think what’s happening here is the Swift 4 version of observe(...) is trying to resolve that path to a static type and cannot, so it’s throwing an error. (Observing only works on NSObject subclasses, as well, so Any could never be observed.) So in this case you would have to use traditional string-based KVO, as “vadian” said.
I'm having a strange issue that appeared with iOS 8 Beta 5 (this issue did not occur with previous versions).
I tried to create an empty project and try to replicate the issue, but I'm unable to do so, so I'm not quite sure where the issue lies.
What I'm seeing is that attempting to access methods of a custom NSManagedObject subclass results in a strange EXC_BAD_ACCESS error.
For example:
var titleWithComma: String {
return "\(self.title),"
}
This method, out of many others, causes this issue when called. However, adding a dynamic keyword before it makes the issue go away:
dynamic var titleWithComma: String {
return "\(self.title),"
}
I know I'm not giving enough info, because I honestly don't know how to pinpoint the actual issue, but can anyone explain what is possibly happening, and why adding dynamic might resolve this issue?
From Swift Language Reference (Language Reference > Declarations > Declaration Modifier)
Apply this modifier to any member of a class that can be represented
by Objective-C. When you mark a member declaration with the dynamic
modifier, access to that member is always dynamically dispatched using
the Objective-C runtime. Access to that member is never inlined or
devirtualized by the compiler.
Because declarations marked with the dynamic modifier are dispatched
using the Objective-C runtime, they’re implicitly marked with the objc
attribute.
It means that your property/method can be accessed by Objective-C code or class. Normally it happens when you sub-classing a Swift class of Objective-C base class.
This is from the prerelease Swift / Objective-C interoperability documentation:
Implementing Core Data Managed Object Subclasses
Core Data provides the underlying storage and implementation of properties in subclasses of the NSManagedObject class. Add the #NSManaged attribute before each property definition in your managed object subclass that corresponds to an attribute or relationship in your Core Data model. Like the #dynamic attribute in Objective-C, the #NSManaged attribute informs the Swift compiler that the storage and implementation of a property will be provided at runtime. However, unlike #dynamic, the #NSManaged attribute is available only for Core Data support.
So, because of some of the Objective-C runtime features that Core Data uses under the covers, Swift properties need to be specially annotated.