had trouble handling threads in swift - swift

I am developing a group call application, after I receive ice I have the following problem:
Thread 1: EXC_BAD_ACCESS (code=1, address=0x40)
Is there any way to solve this?
[]
[enter image description here]4

It seems that either participantJoineds has no element at the first index, or .remotePeer is nil.
You should change the line to:
if participantJoindeds.first?.remotePeer?.remoteDescription != nil {
or even better:
if let description = participantJoindeds.first?.remotePeer?.remoteDescription {
If the method should end after this statement has been evaluated, you could also do:
guard let description = participantJoindeds.first?.remotePeer?.remoteDescription else {
participantJoindeds.first?.arrIceCandidate?.append(iceCandidate)
return
}

Related

Core-data insert multiple objects

i am struggling again to solve a core Data task which keeps failing randomly on me
The following code is building my initial database, which is necessary for the app to work properly
(...)
let context = await (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
(...)
for person in groupOfPeople { //singlePerson (codable Struct) <> SinglePerson (NSManagedObject)
saveSinglePerson(sPerson: person, context: context)
counter+=1
}
logComment = logComment + "..success!(\(counter))"
func saveSinglePerson(sPerson: singlePerson, context: NSManagedObjectContext) {
let newSinglePerson = SinglePerson(context: context)
newSinglePerson.id = sPerson.ID
newSinglePerson.name = sPerson.name
newSinglePerson.age = sPerson.age
(...)
context.performAndWait {
do {
try context.save()
}catch let error {
print(error)
Logging.insertError(message: "IMPORT ERROR: \(error.localizedDescription)", location: "buildDatabase20")
}
}
}
Now here's my problem:
At first i didn't even notice there is a problem, because everything is working fine and all objects get saved as they are supposed to be,
but indeed there is one, because: i am randomly getting an error like so:
error= Error Domain=NSCocoaErrorDomain Code=134030 "An error occurred while saving." UserInfo={NSAffectedObjectsErrorKey=(
"<AppName.SinglePerson: 0x60000104e7b0> (entity: SinglePerson; id: 0x600003337ce0 <x-coredata:///SinglePerson/t3081F988-C5D1-4532-AD81-46F3B4B10215139>; data: {\n id = 138;\n name = testname;\n age = \"25\";\n })"
and i get this error multiple times (20x-150x), with just this one single ID, in this example 138, but it is a different id each time...
i investigate this situation for days now, and i just can't wrap my head around this..
what i found out by now is:
the method should insert 150 rows, and if this error occurs it is not just a count of 149, it's like 87, or 127, or whatever
seems like an object gets stuck in the context, and every execution after the first error fails and is throwing the (same) error..
i tried to fetch those new written data directly after i inserted them, and i always get the same (wrong) count of 150..
i know that this count is not legit because if i take a look at the sqllite file, is see just 87, or 127 or whatever row count..
i do this fetch again with the same context, this is why i think that the issue is within my NSManaged context..
why is this happening on me? and why does this happen sometimes but not all the time?
How do i solve it?
i've found a solution to fix this issue, even though i now know that i will have rework all Core Data interactions from the ground up, to make it real stable and reliable..
this is my first swift project, so along the way things got pretty messy tbh :)
fix: the fact that i save all created objects at once now instead of saving each item on its own, did work and solved the issue for me at this very moment :)
maybe this is helpful for somebody else too ;)
(...)
let context = await (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
(...)
var personArray = [SinglePerson]()
for person in groupOfPeople {
let newSinglePerson = SinglePerson(context: context)
newSinglePerson.id = sPerson.ID
newSinglePerson.name = sPerson.name
newSinglePerson.age = sPerson.age
(...)
personArray.append(newSinglePerson)
}
context.performAndWait {
do {
try context.save()
} catch let error {
print(error.localizedDescription)
}
}

How to fix thread or handle error in Swift?

I can't get rid of an error in the program using Core ML image recognize!
My code is basically debugged and works with a large number of files, but on 421 files the EXC_BAD_ACCESS error occurs (and I changed the order of processing files to eliminate the problem of broken files)
I have already translated all potentially dangerous objects into singletons to avoid leaks, debugged and tidied the sqlite database, rewritten the code using the recommended generateCGImagesAsynchronously operator to get a picture from a video file, everything is cleaned up and works without leaks, but the error still occurs
Directly the code for extracting text objects is taken from the network and slightly upgraded, maybe there is a problem with it?, help!
CreateAltModel3.shared.handler = VNImageRequestHandler(ciImage: inputImage!)
CreateAltModel3.shared.request = VNCoreMLRequest(model: CreateAltModel3.shared.visionModel!) { [weak self] req3, error in
output_handler(req3.results) }
do {try CreateAltModel3.shared.handler!.perform([CreateAltModel3.shared.request!])} catch {print ("hadler3 error - request3")}
here is the code for the output_handler function
func output_handler(_ results: [Any]?) {
guard let results = results as? [VNClassificationObservation]
else {return}
for class1 in results {
if (class1.confidence > 0.05) { // Only show greater than 5%
let fileID = filesArray[currentFileIndex]?.index
if percentRecogn <= Int(round(class1.confidence*100)) {
findKeyStr = (class1.identifier + " " + String(round(class1.confidence*100)) + "%")
resultKeyStr.0 = Int64(fr)
let comma = (resultKeyStr.1 == "") ? "" : ", "
let cutDubbing = (resultKeyStr.1 == class1.identifier) ? resultKeyStr.1 : resultKeyStr.1 + comma + class1.identifier
resultKeyStr.1 = cutDubbing
resultKeyStr.2 = Int64(fileID!)
}
}
}
}
but the error as I understand it occurs after exiting this function
on the next line of code
more code to spread does not make sense because I will only confuse you with extra information, I will only add that this code works in a loop in the global stream and outputs information to the label and ImageView in the main stream as expected, and everything seems to be debugged but I can not understand the nature of the error, perhaps something related to streams but there is not even an idea where to dig)
You cannot (or at least should not) use a single VNCoreMLRequest from multiple threads at a time.

Swift 3 Completion Handler on Google Places Lookup. Due to delay how do I know when Im "done"?

Sorry, newbie here and Ive read extensively about completion handlers, dispatch queues and groups but I just can't get my head around this.
My app loads an array of Google Place IDs and then wants to query Google to get full details on each place. The problem is, due to async processing the Google Lookup Place returns immediately and the callback happens much further down the line so whats the "proper way" to know when the last bit of data has come in for my inquiries because the function ends almost immedately ?
Code is attached. Thanks in advance.
func testFunc() {
let googlePlaceIDs = ["ChIJ5fTXDP8MK4cRjIKzek6L6NM", "ChIJ9Wd6mGYGK4cRiWd0_bkohHg", "ChIJaeXT08ASK4cRkCGpGgzYpu8", "ChIJkRkS4BapK4cRXCT8-SJxNDI", "ChIJ3wDV_2zX5IkRtd0hg2i1LhE", "ChIJb4wUsI5w44kRnERe7ywQaJA"]
let placesClient = GMSPlacesClient()
for placeID in googlePlaceIDs {
placesClient.lookUpPlaceID(placeID, callback: { (place, error) in
if let error = error {
print("lookup place id query error: \(error.localizedDescription)")
return
}
guard let place = place else {
print("No place details for \(placeID)")
return
}
print("Place Name = \(place.name)")
})
}
print("Done")
}

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

FileManager.default.enumerator causes crash when attempting to access unreadable URL

On the face of it, it seems like one should take care when creating directory enumerators, but my code takes a url chosen by the user and it is possible to pick a protected folder in the NSOpenPanel which is then passed in to create the directory enumeration. For example, the user could choose the User/Guest/Desktop folder which is unreadable by a non-guest user.
My handling code (once the url[s] are chosen) is:
if let enumerator: FileManager.DirectoryEnumerator = FileManager.default.enumerator(at: the_url, includingPropertiesForKeys: [URLResourceKey.isReadableKey], options: [.skipsHiddenFiles, .skipsPackageDescendants], errorHandler: { (unreadable_url, error) -> Bool in
print ("Enum error")
DispatchQueue.main.sync(execute: { () -> Void in
self.setStatusText("Cant read url", colour: .red) //Code to update UI on main thread
error_occured = true
})
return false
}) {
//process contents
while let nested_item = enumerator.nextObject() { //....<Crashes
// ..
}
}
Thing is if the url is unreadable (typically because it's protected) then the app crashes at the while.. line with error.
Thread 6: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
No other information is output in Xcode's console. It appears that the enumerator ivar passes the non-nil test despite being unusable and the error block isn't executed so the while statement fails.
My solution has been to check the URLResourceKey.isReadableKey prior to the if let.. line, but that seems like a double-check which shouldn't be necessary.
Is my code wrong or is this a bug?