Why does force Unwrapping give me an EXC_BREAKPOINT (SIGTRAP) Error? - swift

My application is crashing on the declaration of my for loop for participant in event.attendees!. I'm relatively new to swift and understood that if I check that the attendees array is not nil then I'm free to force unwrap it. What have I misunderstood here?
private static func parseParticipants(event: EKEvent) -> [Attendee] {
var participants = [Attendee]()
if(event.attendees != nil && event.attendees?.count != 0) {
for participant in event.attendees! {
let participantName = parseEKParticipantName(participant)
let isRequiredParticipant = participant.participantRole == EKParticipantRole.Required
let hasAccepted = participant.participantStatus == EKParticipantStatus.Accepted
let attendee = Attendee(name: participantName, email: participant.URL.resourceSpecifier!.lowercaseString, required: isRequiredParticipant, hasAccepted: hasAccepted)
participants.append(attendee)
}
}
return participants
}

Turns out this was not about force unwrapping but was due to the EKParticipant.url property returning nil when it contained a String contained a " character.
let attendee = Attendee(name: participantName, email: participant.URL.resourceSpecifier!.lowercaseString, required: isRequiredParticipant, hasAccepted: hasAccepted)
We used this to access the participants email but any read or write operation to the url caused a crash so we took the EKParticipant.description property and parsed the email using a regular expression.
let participantEmail = participant.description.parse(pattern: emailRegex).first ?? ""

How about using optional binding?
if let attendees = event.attendees && attendees.count > 0 {
}

Related

Error in Realm invalid property name when I want to filter data, property not found

I get the error *** Terminating app due to uncaught exception 'Invalid property name', reason: 'Property 'read' not found in object of type 'Book'' when I want to filter my data. My structure:
class Book: Object, Codable {
#objc dynamic var author = ""
#objc dynamic var title = ""
#objc dynamic var imageLink = ""
#objc dynamic var category = "Lk"
#objc dynamic var date = Date()
convenience init(withBookDict: [String: Any]) {
self.init()
self.author = withBookDict["author"] as? String ?? "No Author"
self.title = withBookDict["title"] as? String ?? "No Title"
self.imageLink = withBookDict["imageLink"] as? String ?? "No link"
self.category = withBookDict["category"] as? String ?? "No category"
}
}
my code for filtering data is this:
let filteredread = realm.objects(Book.self).filter({ $0.category == "read"})
but I also tried this:
let filteredread = realm.objects(Book.self).filter("category == 'read'")
also I did update my realm pod since there have been version issues.
There's actually nothing wrong with your code, other than a "typo" - but there's other stuff to consider.
Fixing the typo
let filteredread = realm.objects(Book.self).filter({ $0.category == "read"})
should be
let filteredread = realm.objects(Book.self).filter { $0.category == "read"}
note removing the () from the filter function (which is actually a Swift .filter). This is more for clarity than anything as using swift functions on Realm objects can cause issues.
That query will first read all of the Book objects, then perform a Swift filter on the results and return LazyFilterSequence<Results> object. What that means is the results are disconnected from Realm and will not auto-update, which is one of the key features of realm.
If you want to have the Results update, do not use Swift functions; use Realm functions only
let filteredread = realm.objects(Book.self).filter("category == 'read'")
which returns a Results, which will auto-update as the underlying data changes.
Note: that function matches what's in your question and is perfectly legitimate code and would not throw any errors.
The way to filter Realm results according to a string property is :
let filteredResult = realm.objects(Model.self).filter("propertyName == %#", "value")
In your case it would be:
let filteredread = realm.objects(Book.self).filter("category == %#", "read")

How to remove optional from a string value in swift?

In the code I'm not able to remove optional from the value inside the lbltotalamount.
The value in lblTotalAmount is not removing its optional value from it.
Why? The value in grandtotal gets optional removed but when I assign it to a label it returns an optional value again.
The lblTottalAmount is getting an optional value. I want to remove it.
if success == false {
var grandtotal: Any? = value["total"]
if grandtotal != nil {
print("O!O!O!O/\(grandtotal!)")
grandtotal = String(describing: grandtotal)
self.lblTotalAmount.text = ([grandtotal]) as! String // (here I am not able to remove optional)
}
The problem is in the line
grandtotal = String(describing: grandtotal)
You check for nil but you don't unwrap the value so it's still an optional.
And you are misusing String(describing. Never use it for types which can be converted to String with an init method.
Use always conditional downcast
if success == false {
if let grandtotal = value["total"] as? Double {
self.lblTotalAmount.text = String(grandtotal)
}
}

Form validation issue in macOS app

I am trying to run through a settings form and make sure that the user hasn't left any of the required fields empty.
Some of the forms fields are secure ( eg password).
Whats the easiest way to loop through all these fields and check they are not empty?
I have tried below - but I get a weird error:
if textfield1.stringValue == "",
textfield2.stringValue == "",
passwordfield.stringValue == "" {
//Shows error: Braced block of statements is an unused closure
}
Additionally I am unable to group all these NSTextfields into an array as the password textfields are NSSecureTextField which despite being inherited from NSTextfield, the are not groupable with NSTextfield.
You can have NSTextField and NSSecureTextField in the same array. This is indeed an easy way to find the empty ones.
let tf = NSTextField()
let stf = NSSecureTextField()
let tf2 = NSTextField()
tf2.stringValue = "some text"
let all = [tf, stf, tf2]
let emptyTextFields = all.filter { $0.stringValue.isEmpty }
Also in your example you can't use commas to group conditions in if, you have to use &&:
if tf.stringValue.isEmpty && stf.stringValue.isEmpty && tf2.stringValue.isEmpty {
// do something
}
but this is not a good solution, better use the array and filter.
Under Swift 2, here's what Eric Aya correctly identified:
if textfield1.stringValue == "" && textfield2.stringValue == "" && == "" {
}
It also compiles under Swift 3.
On the other hand, the code you put in your question actually works in Swift 3.
Other way to check empty string with isEmpty variable of String object.
let userName = ""
let email = ""
if(userName.isEmpty && email.isEmpty) {
print("empty strings")
}
else {
print("good strings")
}

How to check if a field type Any? is nil o NSNull

I'm actually trying to parse a Json object with Swift3 on Xcode8.1.
This is my code:
if let objData = objJson["DATA"] as! NSDictionary? {
var msg: String = ""
if let tmp = objData.object(forKey: "Message") {
msg = tmp as! String
} else {
print("NIIILLLLL")
}
}
I'm getting this error message: Could not cast value of type 'NSNull' (0x4587b68) to 'NSString' (0x366d5f4) at this line msg = tmp as! String.
I'm not understanding why I'm getting this error because the type of tmp is Any and it should display the print instead of convert tmp as! String
Thank you for the help,
You can add casting in let.
if let tmp = objData.object(forKey: "Message") as? String {
msg = tmp
}
With Swift 3, for example:
fileprivate var rawNull: NSNull = NSNull()
public var object: Any {
get {
return self.rawNull
}
}
You can check field object as:
if self.object is NSNull {
// nil
}
So to answer your question in why you are getting that error, in your code "tmp" is not nil its something of type NSNull (if you want to know more about NSNull check the docs) but its basically "A singleton object used to represent null values in collection objects that don’t allow nil values."
The rest is just you are force casting which I recommend avoiding this is a safer way to do what you are doing.
guard let objData = objJson["DATA"] as? [String: Any], let msg = objData["Message"] else { return }
// now you can use msg only if exists and also important keeping its unmutable state

How to check nil for Swift Optionals with out unwrap it?

I knew that safely unwrapping is as follows
var firstName:String?
if let firstName = firstName
{
dictionary.setObject(firstName, forKey: "firstName")
}
else
{
dictionary.setObject("", forKey: "firstName")
}
I want to add firstname to dictionary even it is nil also. I will have 10-15 var's in dictionary.
I do not want to check for this condition 10-15 times for ear var.
I am having more than 1000 optionals through out project.
So thought of writing writing a func will help me duplicate the code and reduce the number of lines.
So implemented this func as below.
func checkNull(str:String) -> String
{
return str.characters.count > 0 ? "\(str)" : ""
}
but while calling the func,
let addressstr = self.checkNull(address?.firstName)
firstname is the var in address model here.
The auto correction sugguests
let addressstr = self.checkNull((address?.firstName)!)
The above line causes the crash.
First of all firstName is an Optional therefore you cannot pass it to a function which only takes String.
In addition this line:
str.characters.count > 0 ? "\(str)" : ""
Is equivalent to just returning str so you don't check whether it is an Optional.
Solution
In this case it is way easier to use the nil coalescing operator:
let addressstr = address?.firstName ?? ""
If address is not nil firstName gets unwrapped and bind to addressstr. Otherwise this string gets assigned to it: ""