Recently, I have been working on an application. The goal of the application is to show you your last 10 photos taken in the Today view of the Notification Center, among other things. The application works perfectly in the iOS Simulator, but as soon as I put it on a real device for testing, it fails. It returns the error:
fatal error: Unexpected nil while unwrapping an Optional value
Typically this is very easy to fix since XCode highlights the code that returned nil and gives you the opportunity to fix it. In this case, none of my code gets highlighted. Instead, it highlights a line from Thread 1 (Is this the correct term? Thread 1?), as seen below:
Also note that above the highlited line is the line
; function signature specialization <Arg[0] = Exploded, Arg[1] = Exploded of Swift.(_fatalErrorMessage (Swift.StaticString, Swift.StaticString, Swift.StaticString, Swift.UInt) -> ()).(closure #2)
I included this line in the picture because of the "fatalErrorMessage" part of it. I suspect this could clue me in on the error, but I have no idea what this means. I'm not yet to the point of understanding that.
Also, after some thought, I placed a breakpoint at the viewDidLoad() function in the hopes of tracking any nil values, but the code appears to never even get to this point. It seems as if none of my code is being run.
Has anyone had problems like this/understands what that error code (If that's what it is) means? I'm pretty desperate now, hence me being here.
Thanks,
CodeIt
EDIT:
I placed a println line inside the viewDidLoad function to double check if it was being run. The println function runs and outputs correctly, so I think I may just have messed up my breakpoint somehow. Anyway - the code runs, but it still doesn't highlight any of my code causing the nil value.
EDIT 2:
As requested, I have inserted parts of my code. Please keep in mind that this code is a "first draft", if you will, and I have not yet gotten around to cleaning it up. I'm just trying to get it to work:
#IBOutlet weak var currentPosLabel: UILabel!
var currentImgPos = 0
#IBOutlet weak var imageView: UIImageView!
var images: NSMutableArray!
var totalImageCountNeeded: Int!
func fetchPhotos() {
images = NSMutableArray()
totalImageCountNeeded = 10
self.fetchPhotoAtIndexFromEnd(0)
}
func fetchPhotoAtIndexFromEnd(index: Int) {
let imgManager = PHImageManager.defaultManager()
var requestOptions = PHImageRequestOptions()
requestOptions.synchronous = true
var fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
if let fetchResult = PHAsset.fetchAssetsWithMediaType(PHAssetMediaType.Image, options: fetchOptions) {
if fetchResult.count > 0 {
imgManager.requestImageForAsset(fetchResult.objectAtIndex(fetchResult.count - 1 - index) as? PHAsset, targetSize: view.frame.size, contentMode: PHImageContentMode.AspectFill, options: requestOptions, resultHandler: { (image, _) in
self.images.addObject(image)
if index + 1 < fetchResult.count && self.images.count < self.totalImageCountNeeded {
self.fetchPhotoAtIndexFromEnd(index + 1)
} else {
println("Completed array: \(self.images)")
}
})
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(animated: Bool) {
// NOTE: I am calling the fetchPhotos() function here since earlier in my debugging I thought the problem may be that I was calling it too early in the viewDidLoad function. It an incorrect theory, but it was worth a try.
fetchPhotos()
if images.count > 0 {
imageView.image = images[1] as? UIImage
}
}
I removed some parts of the code that I know have no reasons to cause my error, such as #IBActions, didReceiveMemoryWarning(), etc..
Even it's old question. I found my issue by deleting derived data from xcode.
Xcode -> window->Projects then select and delete your project derived data.
I don't think it is possible to determine exactly where the problem is without seeing your code.
Somewhere in your code you may have forced downcast a variable as!. If you change this to:
if let variable = optionalVariable as? SomeClass {
//Insert your code
}
Then this should fix your problem. Read this to learn more about casting in swift:
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/TypeCasting.html
You should run the same device on simulator and real device.As an example if you run on 5s on real device then try the same device on simulator.By running simulator, it will definitely show the error.My error was the not connecting the #IBActions. Hope that this tip will help you.
I received the same error when trying to set a non-optional value to the value of an implicitly-unwrapped optional that was nil.
Ex. someGlobalFunction() returns an ImplicitlyUnwrappedOptional with a nil value then you try to set that to a regular value.
func someGlobalFunction() -> String! { return nil }
class MyClass {
let aVariable: String
init() {
aVariable = someGlobalFunction()
}
}
Related
I'm working with the Photos framework, specifically I'd like to keep track of the current camera roll status, thus updating it every time assets are added, deleted or modified (mainly when a picture is edited by the user - e.g a filter is added, image is cropped).
My first implementation would look something like the following:
private var lastAssetFetchResult : PHFetchResult<PHAsset>?
func photoLibraryDidChange(_ changeInstance: PHChange) {
guard let fetchResult = lastAssetFetchResult,
let details = changeInstance.changeDetails(for: fetchResult) else {return}
let modified = details.changedObjects
let removed = details.removedObjects
let added = details.insertedObjects
// update fetch result
lastAssetFetchResult = details.fetchResultAfterChanges
// do stuff with modified, removed, added
}
However, I soon found out that details.changedObjects would not contain only the assets that have been modified by the user, so I moved to the following implementation:
let modified = modifiedAssets(changeInstance: changeInstance)
with:
func modifiedAssets(changeInstance: PHChange) -> [PHAsset] {
var modified : [PHAsset] = []
lastAssetFetchResult?.enumerateObjects({ (obj, _, _) in
if let detail = changeInstance.changeDetails(for: obj) {
if detail.assetContentChanged {
if let updatedObj = detail.objectAfterChanges {
modified.append(updatedObj)
}
}
}
})
return modified
}
So, relying on the PHObjectChangeDetails.assetContentChanged
property, which, as documentation states indicates whether the asset’s photo or video content has changed.
This brought the results closer to the ones I was expecting, but still, I'm not entirely understanding its behavior.
On some devices (e.g. iPad Mini 3) I get the expected result (assetContentChanged = true) in all the cases that I tested, whereas on others (e.g. iPhone 6s Plus, iPhone 7) it's hardly ever matching my expectation (assetContentChanged is false even for assets that I cropped or added filters to).
All the devices share the latest iOS 11.2 version.
Am I getting anything wrong?
Do you think I could achieve my goal some other way?
Thank you in advance.
This is a part if code when error happens:
class func randomWord() -> TBWord {
let randomIndex = Int(arc4random_uniform(UInt32(TBAppSettings.wordsForCurrentGame.count)))
let word = TBAppSettings.wordsForCurrentGame[randomIndex]
TBAppSettings.wordsForCurrentGame.removeAtIndex(randomIndex)
MagicalRecord.saveWithBlock { context in
let word = TBWord.findWordWithIdentifier(word.identifier, inContext: context) //here error happens
word?.used = true
}
return word
}
How can I workaround this? I know about other questions about this problem, but they are not enough for me.
(Besides the fact that MagicalRecord is a big misunderstanding of how to use Core Data properly...)
Have you tried to run you code with -com.apple.CoreData.ConcurrencyDebug 1 as a launch argument? This smells like a threading problem.
I'm just starting developing apps with Swift 2.0, and as I'm working having problem with initiating a variable with the value of a text field in my app.
this is the function I'm having problems with. It's called when a button under the text field is pressed as submit.
#IBAction func checkName(sender: AnyObject) {
guard let name : String = nameField.text else { print("Name not valid.");return}
let checker = NameChecker()
let result = checker.nameChecker(name)
print(result)
}
this only thing this code returns on the XCode shell is "lldb". I also tried to use the debugger to figure out where I was messing up but unfortunately I found out that was harder than expected and I wasn't able to.
If you have any idea why my code is only returning "lldb" I would really appreciate is you could let me know since I've been experiencing this error quite often lately.
You might think: "another post about this error".
Yes, i've been looking into this forum before writing this question and unfortunately i couldn't find something that could help, or atleast i know that this error gets on when there is a var that is not bound.
However since im quite new into this, i'd like some help.
I'm following a guide to make a simple infinite side scroller game.
So far everything went good but then i encountered this "nill" error.
The guide itself does not have this error.
So i tought maybe it could be that i use a newer version of xCode or iphone simulation. But im pretty sure its not about that.
My codings so far:
import Foundation
class MainScene: CCNode {
weak var hero: CCSprite!
func didLoadFromCCB() {
userInteractionEnabled = true
}
override func touchesBegan(touch: CCTouch!, withEvent event: CCTouchEvent!) {
// This is the error line. I think it is caused by (applyImpulse(ccp(0, 400)) )
hero.physicsBody.applyImpulse(ccp(0, 400))
}
}
How can i simply fix this?
should i make a variable with applyImpulse?
I also tried to switch between CGPoint (ccp) and CCPackage, both didn't worked.
weak var hero: CCSprite!
This is incredibly dangerous and likely the cause of your problem. Besides using !, which is almost always to be avoided, this mixes it with weak. That means that if something else stops pointing to hero, this variable becomes an implicitly unwrapped nil. The next time you access it, you crash.
First, get rid of the !. If it needs to be weak, use ?. Beyond that, decide if it should really be strong. nothing you've shown here suggests that it should be weak.
I think the error code above can cause much confusion for new people because we don't know what is "optional" in swift 2.0 vs older versions of swift. For example I was getting the same error and could not tell where the problem was. What I found out is that I was making a call to a method using parenthesis () and in the same function I called the method without the parenthesis. This caused the error above. The () are an optional component that became optional with Swift 2.0 the way I understand it. You have to be consistent when calling the methods otherwise the compiler will throw the "Found nil error while unwrapping an optional value". Here is my code: The method I called inconsistently was NSDirectoryEnnumerationOptions(). This is corrected in the example I am sharing:
func listFilesWithFilter() -> [String]
{
NSFileManager().URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: true)
let musicUrl = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first!
do{
let fileList = try NSFileManager.defaultManager().contentsOfDirectoryAtURL(musicUrl,includingPropertiesForKeys: nil, options: NSDirectoryEnumerationOptions())
print(fileList)
} catch let error as NSError {
print(error.localizedDescription)
}
// filter for wav files
do {
let directoryUrls = try NSFileManager.defaultManager().contentsOfDirectoryAtURL(musicUrl, includingPropertiesForKeys: nil, options: NSDirectoryEnumerationOptions())
print(directoryUrls)
let wavFiles = directoryUrls.filter(){ $0.pathExtension == "wav"}.map{ $0.lastPathComponent}
print ("WavFiles:\n" + wavFiles.description)
} catch let error as NSError {
print(error.localizedDescription)
}
return wavFiles
}
Hi I am really new to coding in Swift, and am trying to follow the codes in this book: http://www.apress.com/9781484202098. Learn iOS 8 App Development 2nd Edition by James Bucanek
In particular, I am working through Chapter 3 - building a URL shortening app, but despite having copied the code exactly, I am getting an error on the code in Page 76:
if let toShorten = webView.request.URL.absoluteString {
which states 'NSURLRequest?' does not have a member named 'URL'.
I have tried googling an answer, but unfortunately have not come across anything. Any response I can find seems to suggest that my code ought to be working (e.g. How to get url which I hit on UIWebView?). This seems to have the closest answer SWIFT: Why I can't get the current URL loaded in UIWebView? but the solution does not appear to work for me. If I add a ? after the request, it will then at least build it, but I then have a nil variable returned.
I am using Xcode v6.1.1. Here is the piece of code that is coming up with the error in ViewController.swift:
let GoDaddyAccountKey = "0123456789abcdef0123456789abcdef" //this is replaced by my actual account key in my own code
var shortenURLConnection: NSURLConnection?
var shortURLData: NSMutableData?
#IBAction func shortenURL( AnyObject ) {
if let toShorten = webView.request?.URL.absoluteString { // ? now added
let encodedURL = toShorten.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
let urlString = "http://api.x.co/Squeeze.svc/text/\(GoDaddyAccountKey)?url=\(encodedURL)"
shortURLData = NSMutableData()
if let firstrequest = NSURL(string: urlString) //added if here and removed !
let request = NSURLRequest(URL:firstrequest)
shortenURLConnection = NSURLConnection(request:request, delegate:self)
shortenButton.enabled = false
}
}
}
If you have any suggestions on how I can fix this, I would really appreciate it!
Update:
Following suggestions from Ashley below, I have amended my code so that it is no longer bringing up the error (see comments above). However, it is now no longer running. This appears to be because the urlString is being created as http://api.x.co/Squeeze.svc/text/d558979bb9b84eddb76d8c8dd9740ce3?url=Optional("http://www.apple.com/"). The problem is therefore the Optional() that is included and thus makes it an invalid URL. Does anyone have a suggestion on how to remove this please?
request is an optional property on UIWebView:
var request: NSURLRequest? { get }
also stringByAddingPercentEscapesUsingEncoding returns an optional:
func stringByAddingPercentEscapesUsingEncoding(_ encoding: UInt) -> String?
What you need is to make user of optional binding in a few places:
if let toShorten = webView.request?.URL.absoluteString {
if let encodedURL = toShorten.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding) {
let urlString = "http://api.x.co/Squeeze.svc/text/\(GoDaddyAccountKey)?url=\(encodedURL)"
shortURLData = NSMutableData()
if let firstrequest = NSURL(string: urlString) { // If a method can return a nil, don't force unwrap it
let request = NSURLRequest(URL:first request)
shortenURLConnection = NSURLConnection(request:request, delegate:self)
shortenButton.enabled = false
}
}
}
See Apple's docs on optional chaining for details
See Apple's docs for NSURL class