Swift word count fatal error [closed] - swift

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I am working on a word count function in textViewDidChange. As soon as I type it crashes. When I paste in a sentence, the debugger shows it is getting the word count, but it is crashing when adding the count to the button title with a fatal error: unexpectedly found nil while unwrapping an Optional value.
func textViewDidChange(textView: UITextView) {
let wordCount = textView.text.componentsSeparatedByCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()).count
let words = String(format: "%d", wordCount)
countButton.title = "\(words)"
}

Make sure your countButton is non-nil (check the outlet connection).
Also, the variable in your string interpolation, count, does not seem to be defined - maybe an ivar that is still nil?
Edit:
As it turns out, your countButton is in fact nil and programmatically created. I suspect a definition like so:
weak var countButton : UIButton!
As well as an initialization like so:
self.countButton = UIButton()
The problem is then, that the weak modifier tells the system to not hold ownership of the object. Thus, it immediately gets deallocated after creation.
Try this instead:
let button = UIButton()
self.view?.addSubview(button)
self.countButton = button

The variable wordCount also has a warning saying it was never mutated, consider changing it to let. I assumed var was the was the way to go since the count would change
The count might change. But the value of the variable wordCount will never change, at least in the code you show. The only thing you ever do with it, having created it, is print it. Thus, it should be a let variable, as the compiler suggests.

Related

Why does Swift 5 optional chaining for safeAreaInserts require two question marks in window??.safeAreaInsets instead of one question mark? [duplicate]

When accessing UIapplication's main window it is returned as a UIWindow??
let view = UIApplication.sharedApplication().delegate?.window // view:UIWindow??
Why is it returning as a double optional and what does it mean and if put into a if let should I add one ! after it?
if let view = UIApplication.sharedApplication().delegate?.window!
My first though was to replace ? with a ! after delegate but that was not the solution.
#matt has the details, but there is a (somewhat horrible, somewhat awesome) workaround. (See edit below, though)
let window = app.delegate?.window??.`self`()
I will leave the understanding of this line of code as an exercise for the reader.
OK, I lie, let's break it down.
app.delegate?.window
OK, so far so good. At this point we have the UIWindow?? that is giving us a headache (and I believe is a bug in Swift disconnect between Swift and Cocoa). We want to collapse it twice. We can do that with optional chaining (?.), but that unwraps and rewraps, so we're back where we started from. You can double-optional-chain, though, with ??. which is bizarre, but works.
That's great, but ?? isn't a legal suffix operator. You have to actually chain to something. Well, we want to chain back to itself (i.e. "identity"). The NSObject protocol gives us an identity method: self.
self is a method on NSObject, but it's also a reserved word in Swift, so the syntax for it is `self`()
And so we get our madness above. Do with it as you will.
Note that since ??. works, you don't technically need this. You can just accept that view is UIWindow?? and use ??. on it like view??.frame. It's a little noisy, but probably doesn't create any real problems for the few places it should be needed.
(*) I used to think of this as a bug in Swift, but it's not fixable directly by optional chaining. The problem is that there is no optional chaining past window. So I'm not sure where the right place to fix it is. Swift could allow a postfix-? to mean "flatten" without requiring chaining, but that feels odd. I guess the right operator would be interrobang delegate?.window‽ :D I'm sure that wouldn't cause any confusion.
EDIT:
Joseph Lord pointed out the better solution (which is very similar to techniques I've been using to avoid trivial if-let, but hadn't thought of this way before):
let window = app.delegate?.window ?? nil // UIWindow?
I agree with him that this is the right answer.
It's because the window property is itself in doubt (it's optional). Thus, you need one question mark because there might or might not be a window property, and another question mark because the return value of that window property is itself an Optional. Thus we get a double-wrapped Optional (as I explain in my tutorial: scroll down to the Tip box where I talk about what happens when an optional property has an Optional value).
Thus, one way to express this would be in two stages — one to cast (and unwrap that Optional), and one to fetch the window (and unwrap that Optional):
if let del = UIApplication.sharedApplication().delegate as? AppDelegate {
if let view = del.window {
Now view is a UIWindow.
Of course, if you're sure of your ground (which you probably are), you can force the cast in the first line and the unwrapping in the second line. So, in Swift 1.2:
let del = UIApplication.sharedApplication().delegate as! AppDelegate
let view = del.window!
Oh the double optional! Sometimes you can use a double-bang (two exclamation marks) but you cannot cast that way with optional binding. So... my remix of all the other code gets you a UIWindow object called window of the non-optional kind:
guard let w = UIApplication.shared.delegate?.window, let window = w else { return }
But let's not waste time and just use
let window = UIApplication.shared.delegate!.window!!
and be done.
With advent of Swift2 for me a usual workaround in this kind of cases is
if let _window = UIApplication.sharedApplication().delegate?.window, window = _window {
// Some code... i.e.
let frame = window.frame
}

Swift 5 LLDB error: warning: <EXPR>:12:9: warning: initialization of variable '$__lldb_error_result' was never used

Full Error Message:
error: warning: <EXPR>:12:9: warning: initialization of variable '$__lldb_error_result' was never used; consider replacing with assignment to '_' or removing it
var $__lldb_error_result = __lldb_tmp_error
~~~~^~~~~~~~~~~~~~~~~~~~
_
error: <EXPR>:19:5: error: use of unresolved identifier '$__lldb_injected_self'
$__lldb_injected_self.$__lldb_wrapped_expr_7(
^~~~~~~~~~~~~~~~~~~~~
This error appears in Console when I interrogate the value of a Dictionary<String, String> property within a generic UITableViewController (TVC).
More Detail...
I have a generic TVC (noted above) that is more or less based on the framework outlined in the book "Core Data" by Florian Kugler and Daniel Eggert and takes, amongst other things, a generic value of T.
class TVCDataSource_List<T: Managed, etc...>
This generic TVC includes a dictionary that is designed to hold a list of longer 'alternative' names for the TVC's section headers.
var dictionarySectionData: [String: String] = [:]
I've elected to program the TVC this way because it seems more efficient to hold a reference to a name as a short two character String in the data model attribute (section identifier) than a long name as a String.
I've tried populating this dictionary at many different places in code, most of which work but all with the same outcome, specifically:
I step through the code using the debugger and, as expected, the dictionary is populated via a single fetch request to the persistent store;
Immediately following, a call to print(dictionarySectionData.description) to the console, prints out a properly populated dictionary, as expected;
Interrogating LLDB with p dictionarySectionData (or po) immediately before and after this print to console, produces the Full Error Message detailed at the start of this question;
At the same time, the Assistant Editor Variable Viewer shows the dictionary to be empty, which surprisingly conflicts with the print;
I continue to step through the code to construct the TVC, as the dictionary no longer has its key value pairs, I cannot recall the value for my section header and as expected, the console reports "Fatal error: Unexpectedly found nil while unwrapping an Optional value".
I've done a bit of simple research:
This Blog by Scott Berrevoets titled "Re-binding self: the debugger's break(ing) point".
This Swift Bug Report by Keith Smiley titled "LLDB: warning: initialization of variable '$__lldb_error_result'".
This Swift Bug Report by Zev Eisenberg titled "error: use of undeclared type '$__lldb_context' in NSAttributedString extension".
It seems that I may have either:
stumbled across a bug in the compiler; or
attempted to set the value for the dictionary within the generic TVC such that the compiler interprets an attempt to re-bind to self??
Frankly neither of which I understand and from my shallow knowledge of the compiler and Swift, would take me months, possibly years of learning and experience. Which I'm happy to slowly accumulate over time.
I do have a satisfactory solution... instead of building a dictionary of the longer 'alternative' names for the TVC's section headers at the beginning of the TVC lifecycle, I run a fetch request EACH TIME the code resolves the name for the current TVC section header. This works perfectly and does not block the UI (yet).
However, it really annoys me that I cannot run one fetch at the start of the construction of my generic TVC to prepare a concise dictionary of longer 'alternative' names for the TVC's section headers and instead have to run a fetch for each section that the user decides to scroll through. To perform one fetch and hold a dictionary of 12-15 key value pairs in memory seems far more efficient that running many fetches.
Has any one experienced this problem?
If so, are you able to offer any advice?
UPDATE
The problem seems to be with my use - or perhaps more correctly, my misuse - of the explicitly unwrapped Optional.
Here is the code I use to populate the dictionary...
func createDictionaryOfSectionHeaderText() {
let request = Types.preparedFetchRequest
// noting .preparedFetchRequest is a static var, available through generics
let key = "typeParent.typeParentName"
let name = "Taxonomy"
let predicate = NSPredicate(format: "%K == %#", argumentArray: [key, name])
request.predicate = predicate
var results: [Types] = []
do {
results = try <<My NSManagedObjectContext>>.fetch(request)
}
catch {
let fetchError = error
print(fetchError)
}
for type in results {
let formatSortOrder = String(format: "%02d", type.sortOrder)
dictionarySectionData[formatSortOrder] = type.typeName
}
}
There were two elements of code that caused the error message...
A. As above in the func createDictionaryOfSectionHeaderText()
let stringSortOrder = String(type.sortOrder)
let formatSortOrder = String(format: "%02d", stringSortOrder)
...which was feeding a string into the format "%02d", uncertain of the effect... TBA.
(Now changed from those two lines to the single let formatSortOrder = String(format: "%02d", type.sortOrder) - which of course works.)
B. Within the UITableViewDelegate method func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?
stringHeaderText = dictionarySectionData[stringSectionName]!
// "Fatal error: Unexpectedly found nil while unwrapping an Optional value"
...which, following more thought on the matter, is exactly as expected when explicitly unwrapping the Optional, when that Optional is nil!!
So, when I change the setter to stringHeaderText by removing the instruction to explicitly unwrap, and instead offer a default value when nil, my programming problem disappears.
stringHeaderText = dictionarySectionData[stringSectionName] ?? "ERROR"
I may even provide an answer if/when I understand this better.
These issues should be solved in XCode 12.
There were indeed a lot of bugs in XCode 10 & 11, especially when it came to Generics

Swift performance on optional UI elements

Setting up a UILabel in Swift I can do the following
#IBOutlet var wLabel: UILabel!
or
#IBOutlet var wLabel: UILabel?
Setting the text I can either do
wLabel.text = "..."
or, for the latter do
wLabel?.text = "..." // with a question mark for the optional
Keeping them optional will help for the case when they are unexpectedly nil as it will just skip this call then and go ahead with the code. Having them declared with the ! would crash the app if the label was nil.
Now why would you not make everything optional? The only reason I could think of would be for better performance. Should I stay away from having them optional if my app has a lot of UI elements so them being optional would mean a disadvantage regarding performance? I wasn't able to find any information on this anyhere.
Using ? in your Outlet will make your code untracable
Crashes are very good in some scenarios, because if no crash is there then it becomes super difficult to trace even small error.
Consider the examples of #IBOutlet with !:
#IBOutlet var wLabel: UILabel!
wLabel.isEnabled = true
Just remove the connection of your Outlet label from your storyboard and run the app, your app will crash on wLabel.isEnabled = true. Since you got a crash so you can got to your storyboard see whether the connection is proper or not. In case there is no connect you add it and damn! you solved the problem easily.
Now consider the examples of #IBOutlet with ?:
#IBOutlet var wLabel: UILabel?
wLabel?.isEnabled = true
Do the same thing, just remove the connection of your Outlet label from your storyboard and run the app, your app won't crash at all. You won't be able to know the error, hence making your code a mess and untracable.
Apple guys were very aware of optional thing, they did force unwrapping of #IBOutlet for a reason. And of course there is no performance difference between ! and ?
If you're setting something up as an outlet it's set up as a force unwrapped optional (with exclamation mark !) because Swift requires your classes to have all of their properties initialized when the object is constructed (i.e. init method is called). Outlets are not created during object construction but rather assigned later when the xib or storyboard data is loaded into your component. Force unwrapped optionals are basically a way to say that you guarantee that the property will be initialized after object's init is called and before they're used.
There are no performance gains to using either of these. An Optional? type means that the property can either be nil or have a value. A force unwrapped optional ! means that the property is guaranteed to have a value when it is used. Upholding this is up to the developer and using such property if its value is nil will result in a crash.

UITextField always results in nil

I'm trying to get the information of a UITextField and then reuse that data from the UITextField with swift 2.0 and Xcode 7. But every time I run the app, the app crashes and says:
fatal error: unexpectedly found nil while unwrapping an Optional value
even though there is something in the textfield.
Someone knows how to solve this problem?
This is how my code looks:
#IBOutlet weak var entryAmount: UITextField! //TextField declaration
#IBAction func saveNewButtonTapped(sender: UIBarButtonItem) {
//update overall amount
let amount: String? = self.entryAmount.text! //Throws the error at this point
self.viewController.currentValue += amount
}
In another function, I wrote the same thing ("let amount: String? = entryAmount.text!") and when I printed "amount", it showed the right result. But as soon as I tried to use it further, "amount" was always set to nil, even tough it always printed the right result in the beginning.
I encounter the same thing with DatePicker, Switches and updating Button texts.
Someone knows something to help me? - Thanks
Btw I'm pretty new to swift and Xcode.
Update: Could it be because the TextField is in a ContainerView?
Update Two: I'm pretty much sure the problem is because of the ContainerView. I tried a TextField that isn't in a containerView and didn't get the error, it worked perfectly fine.
Please check in your Interface Builder that the UITextField is properly linked to your "entryAmount" IBOutlet. It might be the case that they are not properly connected and that's why the value is nil at runtime.
I could be wrong but what it seems like from your question is you're having trouble with scoping. Any variables you declare in a function are scoped only to that function.
Declaring amount in saveNewButtonTapped means amount is only set in that function. Using amount in another function will result in amount being nil. If you want to use variables between functions you need to declare them outside of a function.
In the example I have the var runningAmount. In the example, if I press the button that calls pressAnotherButton, I get the same fatal error you get because I'm unwrapping self.runningAmount before it's been set. But if I press the button that calls saveNewButtonTapped, even with nothing in the textfield, then press the button that calls pressAnotherButton, I get the output in the photo.

How do I resolve this circular reference initialization error?

I have a class Question with a nested struct MultipleChoiceAnswers. When initializing Question, I initialize MultipleChoiceAnswers as well, giving it a reference to the Question instance. I then want to assign the MultipleChoiceAnswers instance to the property answers of the Question instance.
Here's an overview:
struct Answer {
let value:Double;
let isCorrect:Bool;
}
class Question {
struct MultipleChoiceAnswers {
let question:Question;
let answers:[Answer];
}
let answers:MultipleChoiceAnswers;
init( possibleAnswersCount:UInt ) {
let answers:[Answer];
/*
here I generate some Answer instances
that get appended to the answers Array
*/
self.answers = MultipleChoiceAnswers( question: self, answers: answers ); // <-- error
}
}
However, this results in the error:
Variable 'self.answers' used before being initalized
This makes sense. Can I resolve this error somehow, though? I was thinking of resolving this with weak or unowned (preferably the latter, since it should be a strong guaranteed non-nil reference), but I don't think I completely understand the logic yet, because changing MultipleChoiceAnswers to:
struct MultipleChoiceAnswers {
unowned let question:Question;
let answers:[Answer];
}
... does not resolve the error.
How can I resolve this error, while keeping a strong guaranteed non-nil circular reference?
P.S.: to be honest, I'm not even entirely sure yet whether I actually need this circular reference to begin with, but since this tentative implementation raised this error, I got curious about a possible resolution anyway.
Just add ! here:
let answers:MultipleChoiceAnswers!
answers needs to have a value prior to passing self to another function. By declaring answers to be an implicit unwrapped optional, you give it the default value of nil. That meets the requirement, and off you go. Since you do give it a value before init finishes, you'll never have trouble with accidentally unwrapping a nil. (But of course you should always be careful with !.)
This is discussed in "Unowned References and Implicitly Unwrapped Optional Properties" in the Swift Programming Guide.