FirebaseMLNLTranslation model files not found - swift

I am adding a translate text feature to my app. I have the text and run the initial setup, but this error keeps coming up.
error: Error Domain=com.firebase.ml Code=13 "Translation model files not found. Make sure to call downloadModelIfNeeded and if that fails, delete the models and retry." UserInfo={NSLocalizedDescription=Translation model files not found. Make sure to call downloadModelIfNeeded and if that fails, delete the models and retry.}
This is the function that translates the text...
translator.translate(textView.text) { [self] translatedText, error in
print("Translator Translated")
guard error == nil, let translatedText = translatedText else {
print(error!); return // prints the error below...
}
print(translatedText) // nil (when I comment out the guard statement)
}
This is the setup code run before the translation.
let options = TranslatorOptions(sourceLanguage: .en, targetLanguage: .es) //
print("Options: \(options)") // Options: sourceLanguage: en, targetLanguage: es
let translator = NaturalLanguage.naturalLanguage().translator(options: options)
print("Translator: \(translator)") // Translator: <FIRTranslator: 0x280173ac0>
let conditions = ModelDownloadConditions (
allowsCellularAccess: true,
allowsBackgroundDownloading: false
); print("Conditions: \(conditions)") // Conditions: allowsCellularAccess: 1, allowsBackgroundDownloading: 0
translator.downloadModelIfNeeded(with: conditions) { error in
guard error == nil else {
print("Model Failed To Download because: \(error!)"); return
}
}
textView.text is not nil. I have no idea how to solve this problem and there are no solutions that I have found online. It actually used to work and I revisited my project after some time off and it all of a sudden started presenting this error. Any help is appreciated.

Related

Got an error when dragging files using NSEvent. (macOS)

I wanna drag files to my window and then perform actions.
I tried to use snippets below provided in this answer to distinguish whether you're dragging a file or a window.
// In my window controller
class MyWindowController: NSWindowController {
init() {
// Some initialization steps below are omitted
let win = NSWindow(...)
super.init(window: win)
let contentView = DropView(frame: win.frame)
win.contentView?.addSubview(contentView)
registerGlobalMouseEvent()
}
func registerGlobalMouseEvent() {
self.window?.acceptsMouseMovedEvents = true
NSEvent.addGlobalMonitorForEvents(matching: .leftMouseDragged, handler: { [self] event in
// Codes below will cause errors
let pasteBoard = NSPasteboard(name: .drag)
guard let fileNames = pasteBoard.propertyList(forType: .init(rawValue: "NSFilenamesPboardType")) as? NSArray else { return }
let changeCount = pasteBoard.changeCount
if fileNames.count > 0 && lastChangeCount != changeCount {
lastChangeCount = changeCount
// My actions when dragging
}
})
}
}
Then I ran my codes and started dragging, I got three errors:
[sandbox] Failed to get a sandbox extension
[Framework] Failed to issue sandbox extension for /Users/roy/Downloads/test.txt with error 1
[default] Failed to issue sandbox token for URL: 'file:///Users/roy/Downloads/test.txt' with error: 'Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted" UserInfo={NSLocalizedDescription=Cannot issue a sandbox extension for file "/Users/roy/Downloads/test.txt": Operation not permitted}'
 
But when I just do
NSEvent.addGlobalMonitorForEvents(matching: .leftMouseDragged, handler: { [self] event in
// My actions
})
, then everything went fine.
 
The first error seems harmless since it didn't prevent my app from running.
The second and the third ones are deadly and directly caused my app to crash.
I wonder if there are any problems in his code? Any useful thoughts would be great! :)
 
You need to know about Bookmarks and Security Scoped URLs when working with sandbox . A dragged URL gives your app process permission just once to read or read/write a “user selected file” depending on how you configure entitlements.
You can save a bookmark (blob of data) to keep access over subsequent sessions as long as the file isn’t updated by another process at which point the bookmark becomes stale and you will need to encourage the user to select the file again.
Handing a URL to another process across an XPC boundary like sharing requires that you own the file so may involve a copy to your sandbox cache.
e.g:
let dragurl = url_of_dragged_file //at this point you have at-least read access
let cachepath = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true).last!
let cachedir = URL(fileURLWithPath: cachepath)
let cacheurl = cachedir
.appendingPathComponent(UUID().uuidString)
.appendingPathExtension(dragurl.pathExtension)
try FileManager.default.copyItem(at: dragurl, to: cacheurl)
At this point you have a copy in your local sandbox cache that can be handed off to a share sheet.
So I finally got a solution for this. :)
It appears that it indeed have something to do with the snippets I mentioned above, and here's the correction:
NSEvent.addGlobalMonitorForEvents(matching: .leftMouseDragged, handler: { [self] event in
let pasteboard = NSPasteboard(name: .drag)
let changeCount = pasteboard.changeCount
if lastChangeCount != changeCount {
lastChangeCount = changeCount
if pasteboard.canReadObject(forClasses: [NSURL.self], options: [:]) {
/// actions
}
}
})
In this way, I got no errors and my codes run perfectly!

waitForExpectations not working as expected in Swift

Trying to write a unit test in Swift 4 for an already working method and having trouble getting the correct result. My current approach is:
let expected = expectation(description: "Obtain access keys")
let keys = sut.retrieveAccessKeys()
//sleep(5)
if keys != nil {
expected.fulfill()
} else {
XCTFail("ERROR: Failed obtaining access keys")
}
waitForExpectations(timeout: 5) { error in
let myError = error as? Error
print("ERROR: \(String(describing: myError?.localizedDescription))")
}
}
The sut makes a network call via a completion handler if the values don't exist within the keychain. The outputted error I get is:
Error: The operation couldn’t be completed. (com.apple.XCTestErrorDomain error 0.)
I've tried various ways including adding in sleep(5). sut. retrieveAccessKeys() does work and the resulting keys contains an optional tuple.

Confused on Error Handling in Swift 3

I got confused error handling in swift3. I try to do like "if XX function got error then try YY function"
Let me show you what I try:
class MyClass {
enum error: Error
{
case nilString
}
func findURL() {
do {
let opt = try HTTP.GET(url_adr!)
opt.start { response in
if let err = response.error {
print("error: \(err.localizedDescription)")
return //also notify app of failure as needed
}
do
{
/* This is func1. and got error. I want to if this function has error then go next function. */
try self.stringOperation(data: response.description)
}
catch{
print("doesn't work on func1. trying 2nd func")
self.stringOperation2(data:response.descritption)
}
}
} catch let error {
print("got an error creating the request: \(error)")
}
}
func stringOperation(data:String)throws -> Bool{
do{
/** 1 **/
if let _:String = try! data.substring(from: data.index(of: "var sources2")!){
print("its done")
}else{
throw error.nilString
}
IN 1: I got this fatal error on this line:
"fatal error: unexpectedly found nil while unwrapping an Optional value" and program crashed.
I googled error handling try to understand and apply to in my code. However not succeed yet. Can someone explain where did I wrong?
Additional info: I got String extension for .substring(from:...) , and .index(of:"str"). So these lines doesn't got you confused.
As a general rule, try avoiding using force unwrapping (!), where you have
if let _: String= try! data.substring...
Instead use
if let index = data.index(of: "var sources2"),
let _: String = try? data.substring(from: index) { ... } else { ... }
That way you remove the two force unwraps that may be causing your crash. You already have the if let protection for catching the nil value, so you can make the most of it by using the conditional unwrapping.

Workaround for EKParcipant URL accessing crash?

Some of my users have been sent me logs identifying a EXC_BREAKPOINT (SIGTRAP) Error on this line of code. I've been been trying to make it safe but all of the properties of EKParticipant are non optional so comparing to nil just gives me a warning saying it will always be true. If something is nil here how should I handle it?
Error Line
let participantEmail : String? = participant.url.absoluteString.lowercased().replacingOccurrences(of: "mailto:", with: "")
Apple Error Description
Trace Trap [EXC_BREAKPOINT // SIGTRAP]
Similar to an Abnormal Exit, this exception is intended to give an
attached debugger the chance to interrupt the process at a specific
point in its execution. You can trigger this exception from your own
code using the __builtin_trap() function. If no debugger is attached,
the process is terminated and a crash report is generated. Lower-level
libraries (e.g, libdispatch) will trap the process upon encountering a
fatal error. Additional information about the error can be found in
the Additional Diagnostic Information section of the crash report, or
in the device's console. Swift code will terminate with this exception
type if an unexpected condition is encountered at runtime such as:
a non-optional type with a nil value
a failed forced type conversion Look at the Backtraces to determine where the unexpected condition was encountered. Additional
information may have also been logged to the device's console. You
should modify the code at the crashing location to gracefully handle
the runtime failure. For example, use Optional Binding instead of
force unwrapping an optional."
Full Method
/**
Parses participants for a given event.
Goes through the EKEvents attendees array to build Attendee objects used to model a participant.
- parameter event: The calendar event we'll be finding the participants for.
- returns: An array of Attendee objects with the participants name, email, required/optional status and whether they've accepted their invitation to the event.
*/
private static func parseParticipantsIn(event: EKEvent) -> [Attendee] {
var participants = [Attendee]()
if let attendees = event.attendees, event.attendees?.isEmpty == false {
for participant in attendees {
let participantName : String? = parse(EKParticipantName: participant)
let participantEmail : String? = participant.url.absoluteString.lowercased().replacingOccurrences(of: "mailto:", with: "")
let isRequiredParticipant : Bool = participant.participantRole == EKParticipantRole.required
let hasAccepted : Bool = participant.participantStatus == EKParticipantStatus.accepted
guard (participantName != nil && participantEmail != nil)
else
{
log.error("Participant could not be parsed")
continue
}
let attendee = Attendee(name: participantName!, email: participantEmail!, required: isRequiredParticipant, hasAccepted: hasAccepted)
participants.append(attendee)
}
}
return participants
}
This appears to be a problem with the EKParticipant.url property. Any attempted access of EKParticipant.url causes a crash if you have a participant with the following email field within it.
"Bill Gates" <billgates#google.com>
I'd guess the quotation marks end the String prematurely. It is fine when accessed from EKParticipant.description so I intend to parse it from there.
This is a ridiculous issue, and Deco pinpointed it exactly. I used a different approach to get around it though: Since I'm already working in a mixed code base (obj-c and Swift), I created a class method on one of my obj-c classes that takes an EKParticipant and returns its URL as a string. Then, in Swift, I call that class method to get the URL instead of directly accessing the property (and crashing). It's hacky, but better than crashing and saved me from parsing the description.
This is rather old question but yet I hit this issue myself. My solution is to fallback to ObjC in order to workaround it.
Just add this ObjC functions to swift bridging header file and you are good to use them in swift.
static inline BOOL
participantHasNonNilURL (EKParticipant* _Nonnull participant) {
return participant.URL != nil;
}
static inline NSURL* _Nullable
participantURL(EKParticipant* _Nonnull participant) {
if (participant.URL != nil) {
return participant.URL;
}else {
return nil;
}
}
Example of usage:
extension EKParticipant {
var optionalURL: URL? {
return participantURL(self)
}
var hasURL: Bool {
return participantHasNonNilURL(self)
}
}
This is still an issue on macOS 11.2... I have reported it to Apple. I encourage anyone else hitting this issue to do the same.
The only Swift-only workaround that worked for me is:
extension EKParticipant {
public var safeURL: URL? {
perform(#selector(getter: EKParticipant.url))?.takeUnretainedValue() as? NSURL? as? URL
}
}
Validations are added incorrectly, please check the below response about how the guard could be used.
if let attendees = event.attendees, event.attendees?.isEmpty == false {
for participant in attendees {
guard let participantName : String? = parse(EKParticipantName: participant) else{
log.error("error in participant name")
return
}
guard let participantEmail : String? = participant.url.absoluteString.lowercased().replacingOccurrences(of: "mailto:", with: "") else{
log.error("error in participant email")
return
}
let isRequiredParticipant : Bool = participant.participantRole == EKParticipantRole.required
let hasAccepted : Bool = participant.participantStatus == EKParticipantStatus.accepted
/* guard validation is not required here */
if (participantName != nil && participantEmail != nil){
let attendee = Attendee(name: participantName!, email: participantEmail!, required: isRequiredParticipant, hasAccepted: hasAccepted)
participants.append(attendee)
}
}
}
return participants

Swift 3 change to NSErrorPointer?

I have code I've been using for SwiftyJSON and I'm trying to update to Swift 3 using XCode 8.0 Beta 3. I'm running into an issue where the compiler doesn't like the argument 'error: &err' as it did before. I've been searching for how to correctly pass an NSErrorPointer but everything I've found says to re-write, leave out the error and throw an error back. Since this isn't my code I'd rather leave it as it is. So what's the correct new way to use an NSErrorPointer?
var err : NSError?
// code to get jsonData from file
let json = JSON(data: jsonData, options: JSONSerialization.ReadingOptions.allowFragments, error: &err)
if err != nil {
// do something with the error
} else {
return json
}
The code above results in compiler error: '&' can only appear immediately in a call argument list. I've tried creating an NSErrorPointer so I can use that instead but I can't find anything on how to initialize one (the type alias declaration is not enough). I've already been to Using Swift with Cocoa and Obj-C, it does not contain the word NSErrorPointer, instead goes over the new way of throwing errors. I've also looked over a couple dozen posts all using the &err so apparently this is new to Swift 3.
Is there anyone out there that's solved this one? What's the answer to using NSErrorPointer?
Thanks,
Mike
That seems to be an error in the Swift 3 branch of SwiftyJSON at
https://github.com/SwiftyJSON/SwiftyJSON/blob/swift3/Source/SwiftyJSON.swift
which defines the init method as
public init(data:Data, options opt: JSONSerialization.ReadingOptions = .allowFragments, error: NSErrorPointer? = nil) {
do {
let object: AnyObject = try JSONSerialization.jsonObject(with: data, options: opt)
self.init(object)
} catch let aError as NSError {
if error != nil {
error??.pointee = aError
}
self.init(NSNull())
}
}
In the Swift 3 that comes with Xcode 8 beta 3, NSErrorPointer is an optional:
public typealias NSErrorPointer = AutoreleasingUnsafeMutablePointer<NSError?>?
as a consequence of
SE-0055: Make unsafe pointer nullability explicit using Optional
Therefore the error parameter should have the type NSErrorPointer,
not NSErrorPointer? (and consequently error??.pointee
changed to error?.pointee).
With these changes the init method becomes
public init(data:Data, options opt: JSONSerialization.ReadingOptions = .allowFragments, error: NSErrorPointer = nil) {
do {
let object: AnyObject = try JSONSerialization.jsonObject(with: data, options: opt)
self.init(object)
} catch let aError as NSError {
if error != nil {
error?.pointee = aError
}
self.init(NSNull())
}
}
and then your code compiles and runs as expected.