Upgrading to Swfit 3: Cannot Override 'Init' Which Has Been Marked Unavailable

Cannot override 'init' which has been marked unavailable prevents overriding empty init

Since NSError is immutable, there's no reason to create multiple instances of the same data. Just create a single, constant, instance:

let NAUnexpectedResponseTypeError = NSError(domain: "MyDomain",
code: 6782,
userInfo: [NSLocalizedDescriptionKey: "The object fetched by AFNetworking was not of an expected type."]
)

If you have a situation that isn't constant, then it is almost always better to extend rather than subclass NSError. For example:

extension NSError {
class func MyError(code code:code, message: String) -> NSError {
return NSError(domain: "MyDomain",
code: code,
userInfo: [NSLocalizedDescriptionKey: message])
}
}

This kind of extension (as a category) has a long history in ObjC, and is a good pattern to bring to Swift (if you can't easily use enum ErrorTypes, which are even better Swift).

In many cases I find it even easier just to have a top-level function for this, rather than extending NSError. For example:

private func makeError(code code:code, message: String) -> NSError {
return NSError(domain: "MyDomain",
code: code,
userInfo: [NSLocalizedDescriptionKey: message])
}

(Personally I use these kinds of functions all the time in Swift when I have to use NSError. In ObjC, I typically used categories on NSError. Not sure why I changed, but it feels more natural.)

Mac Catalyst error: Cannot override 'paymentQueue' which has been marked unavailable

You can prevent code from being compiled into a Mac Catalyst build with the !targetEnvironment(macCatalyst) condition:

#if !targetEnvironment(macCatalyst)
func paymentQueue(_ queue: SKPaymentQueue,
shouldAddStorePayment payment: SKPayment,
for product: SKProduct) -> Bool {
return true
}
#endif

Cannot override method_name which has been marked unavailable in BEMSimpleLineGraph

I got the same problem using the same library. Problem appears to be due to the bridge between OBJ-C and Swift mistaking a deprecated function for the one you're trying to target. I solved it by commenting out code:

1) BEMSimpleLineGraph.h: comment out all the depricated function declarations, it's about 80 lines of code following the

//----- DEPRECATED -----//

2) BEMSimpleLineGraph.m: comment out each time this line appears:

#pragma clang diagnostic ignored

so for instance I removed 7 pairs of lines that looked similar to this:

#pragma clang diagnostic ignored "-Wdeprecated-declarations"
dotValue = [self.delegate valueForIndex:i];

Flutter share facebook : 'init()' has been explicitly marked unavailable here (FBSDKShareKit.ShareDialog)

I've update SwiftFlutterShareMePlugin.swift of flutter_share_me package(version 1.2.0) file as following, and the iOS project is working for facebook sharing.

func sharefacebook(message:Dictionary<String,Any>, result: @escaping FlutterResult)  {
let viewController = UIApplication.shared.delegate?.window??.rootViewController

let shareContent = ShareLinkContent()
shareContent.contentURL = URL.init(string: message["url"] as! String)!
shareContent.quote = message["msg"] as? String
ShareDialog(viewController: viewController, content: shareContent, delegate: self).show()
result("Sucess")

}

I think the problem is because some functions of FBSDKShareKit are deprecated by its version up.

make init() private for NSObject subclass

This answer addresses Swift 2. In Swift 3 it looks like the access level of a method is correctly imported from Swift to Objective-C and does not need to be marked as NS_UNAVAILABLE in order to disallow it from being available. Of course, there is no new method in Swift so that will still need to be marked as NS_UNAVAILABLE to maintain the singleton properly.


Your first approach will work as long as the class is put in its own file. The access control keyword private means that the defined feature will only be available within the containing file.

However, as you said, using the Swift class in Objective-C will remove the protection that private gives you. I believe that's because anything marked private will not have an entry in the imported header file generated by the compiler. Thus the init function inherited from NSObject is available because it isn't overridden.

The solution I found is to create another header file that explicitly declares an init function that can't be called.

Swift class:

@objc(FooClass)
class FooClass: NSObject {
// singleton
static let sharedInstance = FooClass()

let value: String

private override init() {
self.value = "asdf"
}
}

Objective-C header:

@interface FooClass (SharedInstance)
+ (instancetype) new NS_UNAVAILABLE;
- (instancetype) init NS_UNAVAILABLE;
@end

You have to also block new because if you don't then an instance of the class could be created through it.

Testing:

FooClass* foo  = [FooClass sharedInstance]; // All good here
FooClass* foo2 = [[FooClass alloc] init]; // 'init' is unavailable
FooClass* foo3 = [FooClass new]; // 'new' is unavailable

I have a rudimentary example project here: SharedInstance project git



Related Topics



Leave a reply



Submit