Cannot convert call result type 'Set<String>' to expected type 'String' error - macos-catalina

I am working on an old Swift 3 project and I'm getting this error after updating it to Swift 4.2. It seems to work fine in Swift 3. I had to declare let NSURLPboardType = NSPasteboard.PasteboardType(kUTTypeURL as String) because NSURLPboardType does not exist in Swift 4.2 but otherwise the code is the same.
enum SparkleDrag {
static let type = "com.razeware.StickerDrag.AppAction"
static let action = "make sparkles"
}
let NSURLPboardType = NSPasteboard.PasteboardType(kUTTypeURL as String)
var nonURLTYpes: Set<String> {return [String(kUTTypeTIFF), SparkleDrag.type]}
var acceptableTypes: Set<String> {return [nonURLTYpes.union(NSURLPboardType)]}
The "u" in union is underlined with the error but I don't quite understand the nature of the problem. Any guidance would be much appreciated.

The problem is that NSURLPboardType is not a Set<String>, so the union cannot work.
If you're trying to get something like this:
["com.razeware.StickerDrag.AppAction", "public.url", "public.tiff"]
in aceptableTypes, you can simply forgo NSURLPboardType and do this:
enum SparkleDrag {
static let type = "com.razeware.StickerDrag.AppAction"
static let action = "make sparkles"
}
// let NSURLPboardType = NSPasteboard.PasteboardType(kUTTypeURL as String)
var nonURLTYpes: Set<String> {return [String(kUTTypeTIFF), SparkleDrag.type]}
var acceptableTypes: Set<String> {return nonURLTYpes.union([kUTTypeURL as String])}

Related

SwiftUI Text(): Using ternary conditional not localizing

I'm having trouble printing localized text conditionally. For example, this localizes properly:
if valueFromDb.isEmpty {
Text("value_is_empty") //localized text
} else {
Text(valueFromDb)
}
It prints some text in the user's language if valueFromDb is empty, or it prints valueFromDb as it is if it's not. However, when I try to use the ternary operator it doesn't work:
Text(valueFromDb.isEmpty ? "value_is_empty" : valueFromDb)
When valueFromDb is empty, it prints "value_is_empty" rather than actual localized text. I get an error (a random one higher up in the hierarchy thanks to SwiftUI) when trying to cast it as LocalizedStringKey.
Edit: To be clear, I know I can do this:
valueFromDb.isEmpty ? Text("value_is_empty") : Text(valueFromDb)
However, I want to put the ternary conditional inside the Text() brackets because I will do this for several views, and each one will have many modifiers, so the code will become quite bloated.
The problem is due to type inference. You have to declare myString to be of type LocalizedStringKey and then everything will work as expected.
When you declare:
#State var mySrtring: LocalizedStringKey = "whatever"
Then:
Text(myString.isEmpty ? "error_text_localized" : myString)
uses this initializer:
public init(_ key: LocalizedStringKey,
tableName: String? = nil,
bundle: Bundle? = nil,
comment: StaticString? = nil)
When you declare it like this:
#State var mySrtring: String = "whatever"
Then:
Text(myString.isEmpty ? "error_text_localized" : myString)
uses this initialiser:
public init(verbatim content: String)
You have to put your valueFromDb in quotations, then it should work fine.
Text(valueFromDb.isEmpty ? "value_is_empty" : "\(valueFromDb)")

Swift: reflection thanks to infoDictionary

I try to instanciate a new class from a string class name, like we can easy do in Java. I have finally wrote this function:
func stringClassFromString(_ className: String) -> AnyClass! {
let namespace = Bundle.main.infoDictionary!["CFBundleExecutable"] as! String;
let cls: AnyClass = NSClassFromString("\(namespace).\(className)")!;
return cls;
}
Thanks to some googling, but as soon as I tried this solution thanks to a unit test :
func test() {
let myclass = stringClassFromString("NSDate") as! NSDate.Type
let instance = myclass.init()
print(instance)
}
I have an exception (Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)) as soon as my test use the line : let namespace... I tried to see the content of the infoDictionary, he's empty. So my question is simple, is it because of the unit tests context that my dictionary is empty ? Is there any method or library (like robolectric for android) to simulate an infoDicionary for testing purpose.
I succeed to find my error, instead of using the main Bundle, I use the constructor of the Bundle class to build a Bundle which will correspond to the current context :
let namespace = Bundle(for: type(of: self)).infoDictionary!["CFBundleExecutable"] as! String;
And tadda, it's working !

Parse class objects no longer working in Xcode 8.3

I recently updated my Xcode to Xcode 8.3.2 and ran the swift syntax updater. As a result of this update my Parse classes no longer work and I am not sure how fix them.
The error I am receiving is 'Static member 'registerSubclass' cannot be used on instance of type 'County'
The class looks like this.
import Foundation
class County : PFObject, PFSubclassing {
private lazy var __once: () = {
self.registerSubclass()
}()
#NSManaged var Name: String
override class func initialize() {
var onceToken : Int = 0;
_ = self.__once
}
class func parseClassName() -> String{
return "County"
}
}
I am also not understanding why in this update I am getting errors on when using self to call class level methods from within an enclosure?

Error "Value of type ... has no member" while calling self in lazy property closure

Why the following Swift3 code results in error value of type (NSObject) -> () -> MyView has no member getSomeButton in Xcode 8?
lazy var someButton = {
return self.getSomeButton // ERROR
}()
private func getSomeButton() -> UIButton {
return UIButton()
}
Actually, the error message is totally misleading and should be something like can't infer closure return type. Specifying variable type solves the problem. Hope this help someone.
lazy var someButton: UIButton = {
return self.getSomeButton // OK
}()

Why the compiler always wants this type once (=) is overloaded?

I have a problem that I didn't understand since three days, since I don't understand, I can't solve it.
I have code like this:
module SpotLocation = struct
type t = {
uuid : string option;
netElement : string;
coordIntrinsic : float;
}
end
module Segment = struct
type t ={
netElement : string;
coordFrom : SpotLocation.t;
coordTo : SpotLocation.t;
}
let isEqual segA segB = segA.coordFrom = segB.coordFrom && segA.coordTo = segB.coordTo
let (=) = isEqual (* <<<<<<<<< Here is the problem *)
let isIn seg loc = (seg.netElement = loc.netElement)
end
The problem comes from (=) that I have overloaded.
Once I have it, the compiler insists have the following reaction:
Error: This expression has type string but an expression was expected of type t
I have tried to declare the signature of (=) but it doesn't work.
For example, this gives the same thing:
module Segment = struct
type t ={
netElement : string;
coordFrom : SpotLocation.t;
coordTo : SpotLocation.t;
}
let isEqual segA segB = segA.coordFrom = segB.coordFrom && segA.coordTo = segB.coordTo
let ((=) : t -> t -> bool) = isEqual (* <<<<<<<<< Here is the problem *)
let isIn (seg : t) (loc : SpotLocation.t) =
let open SpotLocation in
seg.netElement = loc.netElement
end
If I move the (=) after isIn, it works, but once I start to add some more logic it gives the same error. So I don't know what happens.
Could anyone explain this to me? Thank you!
There is no function overloading in OCaml. Once you define a function (or any other type of value for that matter) with a given name, that name will shadow any existing value with the same name for as long as it is in scope.
So once you define your global = function, the old = is no longer accessible for the rest of the file, except via its fully qualified name Pervasives.=.