I was implementing Firebase friendly chat sample while uploading image. Getting response with optional string. what is missed?
Optional(FIRStorageMetadata 0x7fc84aced790: {
bucket = "abc.appspot.com";
contentEncoding = identity;
contentType = "image/jpeg";
downloadTokens = "abctoken";
generation = 1231231;
metageneration = 1;
name = "Optional(\"S5CKnKUykANdxSvZ3wujpMXHTvg1\")/494509700277/asset.JPG";
timeCreated = "2016-09-02T11:49:00.114Z";
updated = "2016-09-02T11:49:00.114Z";
})
My code:
let filePath = "(FIRAuth.auth()!.currentUser!.uid)/(Int(NSDate.timeIntervalSinceReferenceDate() * 1000))/(referenceUrl.lastPathComponent!)"
was written with optional value (?) in sample so i convert it (!)
In swift you must force unwrap value to avoid this (but make sure, it's not nil).
"\(optionalValue!)"
Or unwrap it in standard way
if let value = optionalValue {
someFIRMethod("\(value)")
}
Related
I have a default value in remote config console like the image above, I need to get that double value. in Android, I can get it like this
val remoteConfig = FirebaseRemoteConfig.getInstance()
val value = remoteConfig.getDouble("parameter_name")
but now I am confused how to get that double value for iOS, it seems there is no getDouble equivalent in swift, so what should I do ?
let remoteConfig = RemoteConfig.remoteConfig()
let value = // what should i write in here ?
You could read it as a String form the config, and then parse the String into a Double.
if let valueAsString = RemoteConfig.remoteConfig().configValue(forKey: "yourKey").stringValue {
if let valueAsDouble = Double(valueAsString) {
// you have your value as a Double now
} else {
print("Not a valid number: \(valueAsString)")
}
}
Firebase also offers "numberValue". The firebase code internally is:
[NSNumber numberWithDouble:self.stringValue.doubleValue]
This means: it returns 0 if the value cannot be converted. You have more control with the String way.
I have XlsxReaderWritter Framework added to my app. I am having trouble with the first steps of using this framework, which is getting a worksheet in an excel file
Here is my code:
let file = BRAOfficeDocumentPackage.open(syllabusFileURL.relativePath)!
inputFile = file.workbook.worksheets[0] //this line does not compile and gives me this "Type [Any]! has no subscript members"
Alright so I cast it as the following:
inputFile = file.workbook.worksheets[0] as! BRAWorksheet
Now it compiles but I get a runtime error saying:
Could not cast value of type 'BRAWorksheet' (0x10df5fdc0) to 'BRAWorksheet' (0x10ce8e430).
So it seems the value is already BRAWorksheet and does not need casting, but as I said it wont compile saying its of type [Any]!
In the official documentation, here is how they get a worksheet;
#####Swift
//First worksheet in the workbook
var firstWorksheet: BRAWorksheet = spreadsheet.workbook.worksheets[0]
//Worksheet named "Foo"
var fooWorksheet: BRAWorksheet = spreadsheet.workbook.createWorksheetNamed("Foo")
Since it is an imported framework, I checked the original Objective-C file for the function. It does not seem to return [Any]!. Here is the body:
- (NSArray *)worksheets {
NSMutableArray *worksheets = #[].mutableCopy;
for (BRASheet *sheet in _sheets) {
BRAWorksheet *worksheet = [self.relationships relationshipWithId:sheet.identifier];
worksheet.styles = _styles;
worksheet.sharedStrings = _sharedStrings;
worksheet.calcChain = _calcChain;
[worksheets addObject:worksheet];
}
return worksheets.count ? worksheets : nil;
}
So can Anyone tell me what the duck is going on??!
If You are using swift 3
let path: String = Bundle.main.path(forResource: "demo", ofType: "xlsx")!
let spreadsheet: BRAOfficeDocumentPackage = BRAOfficeDocumentPackage.open(path)
let worksheet: BRAWorksheet = spreadsheet.workbook.worksheets[0] as! BRAWorksheet
let sheet: BRASheet = spreadsheet.workbook.sheets[0] as! BRASheet
print(sheet.name) // print "Sheet1"
You should take care of the optional result:
var firstWorksheet: BRAWorksheet? = spreadsheet.workbook.worksheets?[0]
let device = devices[indexPath.row]
let deviceTag = device["deviceID"] as? String
cell.slider.tag = deviceTag
I get an error from the above: Cannot assign value of type 'String?' to type 'Int'
This doesn't work (below):
cell.slider.tag = Int(deviceTag)
or what "fix-it" provides:
cell.slider.tag = Int(deviceTag!)!
You need to set optional while casting from string. Try the below code.
let device = devices[indexPath.row]
let deviceTag = device["deviceID"] as! String
cell.slider.tag = Int(deviceTag)
Unless you're 100% sure the value of the dictionary device is an Int you shouldn't implicitly unwrap those optionals.
You can use:
if let deviceTag = deviceTag, tag = Int(deviceTag) { cell.slider.tag = tag }
or
cell.slider.tag = Int(deviceTag) ?? 0
But looking at your examples, it seems like deviceTag isn't a number at all. Perhaps you should look in your debug area (left panel) to see what the value is or simply print(deviceTag) to see what the value is.
I keep getting this error :
fatal error: unexpectedly found nil while unwrapping an Optional value
and cannot figure out how to debug it!
Here's my code :
func readCSV() -> Array<String> {
// Creates a new array of strings
var csvArray : Array<String> = Array<String>()
if let url: NSURL = NSURL(string : "URLFROMCSV" ) {
// Creates an Input Stream that will load the datas from our URL
let data :NSData! = NSData(contentsOfURL: url)!
let stream : NSInputStream! = NSInputStream(data: data)
// Opens the receiving stream
stream.open()
// Sets a buffer with a given size size
let bufferSize = 1024
var buffer = Array <UInt8>(count: bufferSize, repeatedValue: 0)
// String variable initialization
var csvFullString : String = ""
// While the stream receives datas, parses datas, convert them into strings and then concatenate them into one big string
while (stream.hasBytesAvailable) {
let readSize = stream.read(&buffer, maxLength: bufferSize)
let csvRaw = NSString (bytes: &buffer, length: readSize, encoding: NSUTF8StringEncoding)
let csvString = csvRaw as String!
csvFullString = csvFullString + csvString
}
// Fills the array with each strings. Separation between strings is made when a Θ character is parsed
csvArray = csvFullString.componentsSeparatedByString("Θ")
// Delete each null string
for(var i = 0 ; i < csvArray.count; i++) {
if(csvArray[i] == "") {
csvArray.removeAtIndex(i)
}
}
}
return csvArray
}
After searching on the web, I'm pretty sure it has something to do with unwrapping elements but the fact is when I debug it, i don't get any nil value anywhere.
PS: Would like to upload a screen but can't because i don't have 10 reputation, so bad!
Thanks in advance!
EDIT : Line let data :NSData! = NSData(contentsOfURL: url)! got the error.
Terry
You're probably creating the error in one of these two lines (though it may show up later):
let data :NSData! = NSData(contentsOfURL: url)!
let stream : NSInputStream! = NSInputStream(data: data)
You're assigning an optional value to an implicitlyUnwrappedOptional type and then using it without checking if you have a valid value.
This is why if let exists. It's a little funny that you've started to indent as if you're using if let but aren't.
Try this instead:
if let url = NSURL(string : "http://gorillaapplications.com/etablissements.csv" ) {
// Creates an Input Stream that will load the datas from our URL
if let data = NSData(contentsOfURL: url) {
let stream = NSInputStream(data: data)
stream.open()
// rest of your code here
}
else {
println("Didn't get a data object")
}
}
else {
println("Didn't get a URL object")
}
You really need to grasp Optionals for Swift. I'd recommend reading my Optionals chapter in this iBook: https://itunes.apple.com/us/book/swift-optionals-generics-for/id943445214?mt=11&uo=4&at=11lMGu
Update:
Since you added a bit more in your comments above, you're saying you get the error on this line: let data: NSData! = NSData(contentsOfURL: url)!. This is because of the ! at the end, which tells Swift you're sure that this function will return a valid value, so just use it, without checking if it's nil first. In your case, the function is returning nil and so your app crashes. Using the sample code I've provided above, you'll see that you'll no longer get a crash, but your code will execute the "Didn't get a data object" line. You'll need to correctly handle the case where you can't load data from that URL.
I have this json result.
I would take the field "alert".
I try this:
var alert: NSString = jsonResult["features"]["properties"]["alert"]
but this is the error: does not have a member named 'subscript'.
I can not how to access a field in a nested dictionary
{
features = (
{
geometry = {
coordinates = (
"-97.95359999999999",
"37.2382",
5
);
type = Point;
};
id = usb000si7g;
properties = {
alert = green;
cdi = "5.8";
code = b000si7g;
detail = "http://earthquake.usgs.gov/earthquakes/feed/v1.0/detail/usb000si7g.geojson";
dmin = "0.017";
felt = 1258;
gap = 38;
ids = ",usb000si7g,";
mag = "4.3";
magType = mwr;
mmi = "4.94";
net = us;
nst = "<null>";
place = "8km SE of Harper, Kansas";
rms = "0.51";
sig = 864;
sources = ",us,";
status = reviewed;
time = 1412272884590;
title = "M 4.3 - 8km SE of Harper, Kansas";
tsunami = "<null>";
type = earthquake;
types = ",cap,dyfi,general-link,geoserve,losspager,moment-tensor,nearby-cities,origin,phase-data,shakemap,tectonic-summary,";
tz = "-300";
updated = 1412614943519;
url = "http://earthquake.usgs.gov/earthquakes/eventpage/usb000si7g";
};
type = Feature;
}
);
metadata = {
api = "1.0.13";
count = 1;
generated = 1412617232000;
status = 200;
title = "USGS Significant Earthquakes, Past Week";
url = "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/significant_week.geojson";
};
type = FeatureCollection;
}
I don't know what to do. swift is changed every beta.
As #Kirsteins said is his answer, you have to do a lot of unwrapping, and it's recommended to use a JSON library.
If you still want to stick with hand made extraction, then I suggest you to made it programmatically, such as adding an extension to NSDictionary as follows:
extension NSDictionary {
func objectForTreeKeys<T>(keys:[String]) -> T? {
var dict: NSDictionary? = self
var retValue: T?
for key in keys {
var value: AnyObject? = dict?.objectForKey(key)
if let unwrapped = value as? NSDictionary {
dict = unwrapped
} else if let unwrapped = value as? T {
retValue = unwrapped
break
} else {
retValue = nil
break
}
}
return retValue
}
}
You pass an array of keys to the function, and it traverses all nested dictionaries until:
a value of type T is encountered
a value having type different than NSDictionary and T is found
a nil value is found
In the first case, it returns the value of T type - in the other cases it returns nil.
You can use it as follows:
let ret: String? = jsonResult.objectForTreeKeys(["features", "properties", "alert"])
As you can see, it's a generic method, and the return type is inferred from the type of the variable the result is assigned to - so it's necessary to explicitly define its type, which must be optional (String? in this specific case).