'PFObject values may not have class: NSConcreteValue' - ios

App keeps crashing on this Method - trying to simply pin a Parse object to the local data store as outlined in the docs Parse docs:
func saveToBackground(title:String, description:String, coords:CLLocationCoordinate2D, image:UIImage, objectId:String, dateFound:String){
let imageData = image.jpeg(.low)
let imageFile = PFFile(name: "image.png", data: imageData!)
let foundObject = PFObject(className: "FoundObjects")
foundObject["title"] = title
foundObject["description"] = description
foundObject["coordinates"] = coords
foundObject["image"] = imageFile
foundObject["objectId"] = objectId
foundObject["dateFound"] = dateFound
foundObject.pinInBackground()
}
error:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'PFObject values may not have class: NSConcreteValue'
Any ideas anyone?

At least one of your values is an NSConcreteValue class, which can't be stored on a PFObject. Figure out which line is causing the issue by setting a breakpoint and stepping through, and make sure to cast that value to the expected class. Or you could cast all of these to their expected class, cover your bases.
Edit: As pointed out by MartynE23, the issue was actually the CLLocationCoordinate2D, which must be converted to a PFGeoPoint to add to a Parse Object

Related

Trying to create MapImage instance for map marker in Here Explore for iOS is giving a weird error

Here Explore
init(coordinates: GeoCoordinates, image: UIImage) {
let pngData = image.pngData()
let mapImage = MapImage(pixelData: pngData!, imageFormat: ImageFormat.png)
print("i did print")
self.mapMarker = MapMarker(at: coordinates, image: mapImage)
}
This is the error message -
dyld4 config: DYLD_LIBRARY_PATH=/usr/lib/system/introspection
DYLD_INSERT_LIBRARIES=/Developer/usr/lib/libBacktraceRecording.dylib:/Developer/usr/lib/libMainThreadChecker.dylib:/Developer/Library/PrivateFrameworks/DTDDISupport.framework/libViewDebuggerSupport.dylib:/usr/lib/libMTLCapture.dylib
terminating with uncaught exception of type std::runtime_error: SDK
engine is null. Please provide a valid object.
pngData isn't a nil value when the MapImage constructor is called, I checked it by printing. What does this error mean and how can I fix it?
I figured this out myself. The crux of the issue is that before creating the MapImage instance the HereSDK engine needs to be initialized which can be done in 2 ways-
Initialize the MapView which in turn initializes the HereSDK engine but in my case this initialization was happening after the MapImage instance initialization statement.
Initialize the engine explicitly before the MapImage instance initialization statement.
do {
try SDKInitializer.initializeIfNecessary()
} catch {
fatalError("Failed to initialize HERE SDK. Cause: (error)")
}
This can be done in the AppDelegate file as well.

Unable to set <UIImage:0x283942880 anonymous {1080, 1080} renderingMode=automatic> to UIImageView XCode Swift

I have built an app which fetches contacts from phonebook and saves their name and photo. To save the photo I've used the following code
if let imageData = contact.thumbnailImageData {
imageStr = String(describing: UIImage(data: imageData)!)
} else {
imageStr = "null"
}
and when I print imageStr using print("IMGSTR: \(imageStr)") I get the following output
IMSTR: <UIImage:0x283942880 anonymous {1080, 1080} renderingMode=automatic>
Now I'm stuck on how to set this string to the UIImageView, I tried
imageview.image = UIImage(named: imageStr)
but it shows nothing
Could someone please help me in how to set the string <UIImage:0x283942880 anonymous {1080, 1080} renderingMode=automatic> to UIImageView?
No need to convert it to a String. UserDefaults supports Data objects. Store it as Data and when setting it to a UIImageView use let image = UIImage(data : imageData)
If you want to convert an instance of Data to String, you should use the String(decoding:as:) initializer, like this.(eg : let str = String(decoding: data, as: UTF8.self)).

What could be the cause of an occasional failure to create an encrypted Realm object?

I've got a released app using Realm and there are some crash logs showing that there is sometimes a failure to create the realm with a configuration resulting in a EXC_BREAKPOINT (SIGTRAP) crash. (there's 9 crash files for a few hundred app installations so its not something which is happening frequently)
#objc class Database : NSObject
{
let configuration = Realm.Configuration(encryptionKey: Database.getKey() as Data)
var transactionRealm:Realm? = nil
override init()
{
let realm = try! Realm(configuration: configuration) // Crash here
<snip>
}
// This getKey() method is taken from the Realm website
class func getKey() -> NSData {
let keychainIdentifier = "Realm.EncryptionKey.AppKey"
let keychainIdentifierData = keychainIdentifier.data(using: String.Encoding.utf8, allowLossyConversion: false)!
// First check in the keychain for an existing key
var query: [NSString: AnyObject] = [
kSecClass: kSecClassKey,
kSecAttrApplicationTag: keychainIdentifierData as AnyObject,
kSecAttrKeySizeInBits: 512 as AnyObject,
kSecReturnData: true as AnyObject
]
// To avoid Swift optimization bug, should use withUnsafeMutablePointer() function to retrieve the keychain item
// See also: http://stackoverflow.com/questions/24145838/querying-ios-keychain-using-swift/27721328#27721328
var dataTypeRef: AnyObject?
var status = withUnsafeMutablePointer(to: &dataTypeRef) { SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0)) }
if status == errSecSuccess {
return dataTypeRef as! NSData
}
// No pre-existing key from this application, so generate a new one
let keyData = NSMutableData(length: 64)!
let result = SecRandomCopyBytes(kSecRandomDefault, 64, keyData.mutableBytes.bindMemory(to: UInt8.self, capacity: 64))
assert(result == 0, "REALM - Failed to get random bytes")
// Store the key in the keychain
query = [
kSecClass: kSecClassKey,
kSecAttrApplicationTag: keychainIdentifierData as AnyObject,
kSecAttrKeySizeInBits: 512 as AnyObject,
kSecValueData: keyData,
kSecAttrAccessible: kSecAttrAccessibleAfterFirstUnlock
]
status = SecItemAdd(query as CFDictionary, nil)
assert(status == errSecSuccess, "REALM - Failed to insert the new key in the keychain")
return keyData
}
Here's the relevant portion of the crash file:
Exception Type: EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000001, 0x0000000103c0f30c
Termination Signal: Trace/BPT trap: 5
Termination Reason: Namespace SIGNAL, Code 0x5
Terminating Process: exc handler [0]
Triggered by Thread: 0
Thread 0 name:
Thread 0 Crashed:
0 libswiftCore.dylib 0x0000000103c0f30c 0x103ab4000 + 1422092
1 libswiftCore.dylib 0x0000000103c0f30c 0x103ab4000 + 1422092
2 libswiftCore.dylib 0x0000000103b13d2c 0x103ab4000 + 392492
3 libswiftCore.dylib 0x0000000103b13bf4 0x103ab4000 + 392180
4 My app 0x000000010334ff14 _TFC14Caller_Name_ID8DatabasecfT_S0_ + 1648 (Database.swift:21)
5 My app 0x0000000103330624 -[Model createDatabase] + 200 (Model.m:271)
Line 21 of the Database.swift file is the one indicated in the code above in the Init() method.
If the reason for the Realm crash is because getKey() fails, then why would that be failing? If thats not the cause, that what are other reasons for the failure?
And is there anything the code can do (such as retry to create the Realm object) if there is a failure?
The init method
I'm going to get this out of the way first: It's unlikely that this has anything to do with your crash in this instance, but when you override any init method, you should always call super's version of that init method unless there is no super class or no available superclass implementation to call. In Objective-C you assign the results of [super init] to self, however, this pattern was not adopted by swift and it is unclear, from Apple's documentation, what happens when you call super.init() from a direct NSObject subclass in Swift. I'm running out of steam at this hour, thought I did spend some time looking at the apple/swift GitHub repository Apple/Swift Github among other place and was unable to find any really satisfying information about calling NSObject init from a Swift subclass. I would definitely encourage you to continue the search if you really want to know more and not just take my word for it. Until then, it is highly unlikely that it will cause issues if you call NSObject's init() from a Swift subclass and it just might save your butt at some point too! ;)
The crash
If the reason for the Realm crash is because getKey() fails, then why would that be failing?
I'm not sure why getKey() might be failing, but it's unlikely this is the cause of your crash. I believe default values for properties are available by the time code inside init() is called in which case your app would crash before it reached that call inside init(). I will do a little more research on this tomorrow.
If thats not the cause, that what are other reasons for the failure?
I've looked at the Realm API you are using there and it's unclear why the call to Realm(configuration:) is failing although clearly that's expected to be possible since the call can throw. However, the documentation doesn't state the conditions under which it will throw.
And is there anything the code can do (such as retry to create the Realm object) if there is a failure?
Yes! Fortunately, the "try" mechanism has other variation than just "try!". Actually, in this case, the reason the app appears to be crashing is that you are using try! which in production code should only be used in situations where you know the call is extremely unlikely to ever fail such as retrieving a resource your app ships with from inside it's app package. Per Apple's documentation:
Sometimes you know a throwing function or method won’t, in fact, throw an error at runtime. On those occasions, you can write try! before the expression to disable error propagation and wrap the call in a runtime assertion that no error will be thrown. If an error actually is thrown, you’ll get a runtime error. Swift Error Handling Documentation
When it comes to impacting the user experience, I always like to err on the side of caution so I would be highly surprised to find even one occurrence of try! in any of my code (even Swift playground toys and experiments).
In order to fail gracefully and retry or take another course of action your code either needs to use try? which will convert the thrown error to an optional as in:
if let realm = try? Realm(configuration: configuration) {
// Do something with realm and ignore the error
}
Or you can use a full try-catch mechanism like so:
let realm: Realm? = nil
do {
realm = try Realm(configuration: configuration)
// do something with realm
} catch let e {
realm = nil
// do something with the error
Swift.print(e)
}
Or alternatively:
do {
let realm = try Realm(configuration: configuration)
// do something with realm
} catch let e {
// do something with the error
Swift.print(e)
}
So this may not be your golden ticket to never having this Realm call fail, but I hope it provides some help towards making your code a little more robust. I apologize for any errors, it's getting late for me here. Good luck and cheers! :)

Swift 3 - SIGABRT when trying to retrieve data from FirebaseSnapshot

Following this tutorial on implementing the Firebase Database into my app: Video
When I try to retrieve the data in the 'events' tree, the app crashes. Currently, I'm attempting this through
let date = events[(self.events.count - 1) - (indexPath).row]?.value("date") as! String
and it's throwing a Thread 1: signal SIGABRT error, at that line.
The console is telling me
Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<FIRDataSnapshot 0x17003f680> valueForUndefinedKey:]: this class is not key value coding-compliant for the key date.'
So what am I doing wrong? Or is there a better way to do this?
The issue is in the code you're using to fetch the date.
let date = events[(self.events.count - 1) - (indexPath).row]?.value("date") as! String
Based on the structure of your data in Firebase, the above code is looking for the key "date" two levels below "events". In your Firebase data, the "date" key is three levels below events, not two. Here's what you can do to solve the problem:
let oneStepBelow = events[(self.events.count - 1) - (indexPath).row] as! [AnyObject]
let secondStep = oneStepBelow[0].value("date") as! String
This should solve your problem.

xcode crashes when I click on the console to check the output

Facing an issue with xcode.
I'm trying to develop an app that gives me the weather info. The build succeeds, but everytime I click on the console to check the output (to search, copy etc) xcode crashes.
The following text comes from the reporting tool to Apple,
Application Specific Information:
ProductBuildVersion: 7C1002
UNCAUGHT EXCEPTION (NSRangeException): -[__NSCFString characterAtIndex:]: Range or index out of bounds
UserInfo: (null)
Hints: None
Here's the code I'm running,
override func viewDidLoad() {
super.viewDidLoad()
let url = NSURL(string:"http://www.weather-forecast.com/locations/Hyderabad/forecasts/latest")
let task = NSURLSession.sharedSession().dataTaskWithURL(url!) { (data, response, error) -> Void in
if let webContent = data {
let decodedContent = NSString(data: webContent, encoding: NSUTF8StringEncoding)
//print(decodedContent)
let weatherSiteSourceArray = decodedContent?.componentsSeparatedByString("3 Day Weather Forecast Summary:</b><span class=\"read-more-small\"><span class=\"read-more-content\"> <span class=\"phrase\">")
print(weatherSiteSourceArray)
// if weatherSiteSourceArray?.count > 0 {
//
// let weatherInfo = weatherSiteSourceArray![1]
// print(weatherInfo)
// }
}
}
task.resume()
// Do any additional setup after loading the view, typically from a nib.
}
though the report tool informs me UNCAUGHT EXCEPTION (NSRangeException): -[__NSCFString characterAtIndex:]: Range or index out of bounds.
I am unable to figure out where this is happening.
From what i have learned you can print an array in Swift using the print(items: Any...) method.
help on this would be greatly appreciated !
You are checking is there any element in your array and then you are trying to read second element. There are chances that your array is having only one item in it and hence when you are choosing weatherSiteSourceArray![1], it fails as accessing element 2 is out of bound of array.
if weatherSiteSourceArray?.count > 0 {
let weatherInfo = weatherSiteSourceArray![1]
Either check for
if weatherSiteSourceArray?.count > 1
or use first element i.e.
let weatherInfo = weatherSiteSourceArray![0]
I have no idea of swift and assume it uses zero based index for array.
A good place to start would be to figure out exactly which line is causing the crash. Try commenting out these three lines:
let decodedContent = NSString(data: webContent, encoding: NSUTF8StringEncoding)
//print(decodedContent)
let weatherSiteSourceArray = decodedContent?.componentsSeparatedByString("3 Day Weather Forecast Summary:</b><span class=\"read-more-small\"><span class=\"read-more-content\"> <span class=\"phrase\">")
print(weatherSiteSourceArray)
And if you code doesn't crash after that, then try commenting in you code one line at the time until you have the line crashing.
Another thing:
Looking at your code I'm guessing that maybe this line:
let weatherSiteSourceArray = decodedContent?.componentsSeparatedByString("3 Day Weather Forecast Summary:</b><span class=\"read-more-small\"><span class=\"read-more-content\"> <span class=\"phrase\">")
might be the one causing your problems. Its a bit risky and brittle to try separating your content based on an HTML string like that. The second that string changes (and it will :-)), you've lost.
A better way would be to receive the data in pure JSON or XML if they have an API providing that.
Just a thought :-)

Resources