base64EncodedStringWithOptions in Swift fails with compile error - ios

let dataStr = data.base64EncodedStringWithOptions(options: Encoding64CharacterLineLength)
Doesn't compile with "Use of unresolved identifier 'Encoding64CharacterLineLength'"
When I just change the param to zero with
let dataStr = data.base64EncodedStringWithOptions(options: 0)
It gives even stranger error: "Cannot convert the expression of type 'String!' to type 'String!'" I found a way to init NSString with NSData (however, I still can't get the difference between String and NSString), but I'm really curious why these two lines of code don't work.

Unless explicitly given an external name, first argument of a method in Swift is not a named argument. Therefore you should be doing: data.base64EncodedStringWithOptions(x) without the options: part.
If you actually look at the argument type, NSDataBase64EncodingOptions, you'll notice that it is a struct conforming to RawOptionSet with static variables for option constants. Therefore to use them you should do: NSDataBase64EncodingOptions.Encoding64CharacterLineLength
The NSDataBase64EncodingOptions struct (or RawOptionSet in general) is also not convertible from integer literals (like 0). But it does conform to NilLiteralConvertible so if you don't want any options you can pass nil.
Putting it together:
let dataStr = data.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.Encoding64CharacterLineLength)
or
let dataStr = data.base64EncodedStringWithOptions(nil)
Swift3.0
let dataStr = data.base64EncodedString(options: [])

For Swift 2.x use an array for options:
let dataStr = data.base64EncodedStringWithOptions([.Encoding64CharacterLineLength])
let dataStr = data.base64EncodedStringWithOptions([])

For swift 3.0+ use this ,
var dataStr = data.base64EncodedString(options: .lineLength64Characters)

Swift 3.x
let fileStream = fileData?.base64EncodedString(options: NSData.Base64EncodingOptions.init(rawValue: 0))

You don't have to put in the "options:" identifier in the argument. You DO have to specify that Encoding64CharacterLineLength is a static member of NSDataBase64EncodingOptions, like so:
var dataStr = data.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.Encoding64CharacterLineLength)

let dataStr = data.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.allZeros)

Since the default parameter value is set be an empty array…
/// Returns a Base-64 encoded string.
///
/// - parameter options: The options to use for the encoding. Default value is `[]`.
/// - returns: The Base-64 encoded string.
#inlinable public func base64EncodedString(options: Data.Base64EncodingOptions = []) -> String
you just need to call
let dataStr = data.base64EncodedString()

Related

Cannot assign value of type String to type AnyObject? Swift 3.0

I am suddenly getting this error for a dictionary of type:
var parameters = [String: AnyObject]()
and then if I try:
parameters["cancelled_by"] = someUser ?? ""
I am getting the error as :
Cannot assign value of type String to type AnyObject?
This is for Swift 3.0. What am I doing wrong here? Why doesn't it work?
String is the value type. AnyObject only accepts reference types. So in order to add both value types and reference types in Dictionary use Any instead of AnyObject, i.e.
var parameters = [String: Any]()
This is an addition to Swift 3.0.
I'm starting with Swift 3 right now, a bit late... however, until Swift 2.2 some Swift value types were automatically bridged to the corresponding foundation reference types, such as String to NSString, Dictionary<> to NSDictionary, and so forth. It looks like this automatic bridging has been removed in Swift 3.
There are cases where turning a [String : AnyObject] into [String : Any] makes sense, in others it doesn't, depending on what you're doing. In my current case, where I need reference types, it doesn't.
So I am solving the problem by requesting an explicit bridging, by casting to AnyObject:
var dictionary: [String : AnyObject] = [:]
dictionary["valueType"] = "Value Type" // Error
dictionary["referenceType"] = "Reference Type" as AnyObject // OK
For reference:
let text = "Text"
let asAny = text as Any
let asAnyObject = text as AnyObject
let asNSString: NSString = text as NSString
type(of: text) // Prints String.Type
type(of: asAny) // Prints String.Type
type(of: asAnyObject) // Prints _NSContiguousString.Type
type(of: asNSString) // Prints _NSContiguousString.Type

`CountedSet` initialization issue

I'm comparing the characters contained within two words. In seeking to accomplish this, Set (aka NSSet) seemed like the way to go to accomplish this task. I've discovered it returns false positives on matches, so I am attempting to use CountedSet (aka NSCountedSet) instead.
I'm able to initialize a Set without issue, but I can't get the CountedSet initializer to work. Here's what I've done...
I start with a String:
// Let's say myTextField.text = "test"
let textFieldCharacters = myTextField.text?.characters
// word is a string from the ENABLE list of words
let wordCharacters = word.characters
Then I dump the characters into an Array:
var wordCharactersArray = [Character]()
for character in wordCharacters {
wordCharacterArray.append(character)
}
var textFieldCharactersArray = [Character]()
for character in textFieldCharacters {
wordCharacterArray.append(character)
}
Then I create a Set from the character arrays:
let textFieldSet = Set<Character>(textFieldCharactersArray)
let wordSet = Set<Character>(wordCharactersArray)
Finally, I test to see if the textFieldSet is a superSet of wordSet with the following:
textFieldSet.isSuperset(of: wordSet)
Going back to my example, if myTextField.text is "test", I'm returning values for word whose characters are a superset of the wordSet, but the counts of the individual elements don't match the character counts of myTextField.text
In researching my issue, I've found CountedSet (fka NSCountedSet), which I think would resolve my issue. It has two method signatures:
public convenience init(array: [AnyObject])
public convenience init(set: Set<NSObject>)
I've tried initializing the 2 sets of characters like so:
let textFieldSet = CountedSet(array: textFieldCharacterArray)
let wordSet = CountedSet(array: wordCharacterArray)
I get the following error for the sets
Cannot convert value of type '[Character]' to expected argument type
'[AnyObject]'.
So I tried initializing the set like this:
let textFieldSet = CountedSet(array: textFieldCharacterArray as! [AnyObject])
Which yields the following error:
'AnyObject' is not a subtype of 'Character'
I've also tried to initialize the CountedSet with a Set, per the method signature, but I get errors when I try to do that, too.
Any suggestions how to initialize a CountedSet would be greatly appreciated.
You are correct that if you need to compare not just the presents of elements but also their count, you should use CountedSet, which is a renaming of NSCountedSet for swift 3.0. The problem you are running into is CountedSet can only accept elements that are objects and Characters are not. As Eric D points out in their comment, the easies way to get around this is by mapping your [Character] to [String] which will bridge to [NSString].
You are not running into this problem using Set, because it is a native Swift collection type that initialize with elements of any type. This is why you can initialize a Set with [Character].
To see the difference:
let word = "helo"
let wordCharacters = Array(word.characters)
let wordSet = Set(wordCharacters)
let wordCharStrings = wordCharacters.map{String($0)}
let wordCountedSet = CountedSet(array: wordCharStrings)
let textField = "hello"
let textFieldCharacters = Array(textField.characters)
let textSet = Set(textFieldCharacters)
let textFieldCharStrings = textFieldCharacters.map{String($0)}
let textFieldCountedSet = CountedSet(array: textFieldCharStrings)
textFieldCountedSet.isSubset(of: wordCountedSet as! Set<NSObject>) // returns false, but if word had two or more l's it would return true
textSet.isSubset(of: wordSet) // returns true

Swift NSArray subscript a value of type AnyObject

This my my NSArray
var RidesData:NSArray = []
It is used to store an JSON Array i have converted
RidesData = NSJSONSerialization.JSONObjectWithData(jsonData, options: nil, error: &error) as! NSArray
Sample of the Array
Optional((
{
ContentType = USSShow;
Name = "Lake Hollywood Spectacular\U00ae (Seasonal Show)";
NextShowTime = "8:00pm";
NextTimeSlot = "";
QueueTime = "";
TimeSlot = "";
},
I am trying to get the Name value using this code
let RideName = RidesData[indexPath.section]["Data"][indexPath.row]["Name"]
cell.textLabel!.text = RideName
However i am getting this error
Cannot subscript a value of type 'AnyObject?!' with an index type of 'int'
From what i have searched, i believe that i am unable to subscript because it is an optional but when i tried to unwrap it with ! it gives me this error
Operand of postfix "!" should have optional type; type is 'NSArray'
How can i solve this problem?
Try:
let RideName = RidesData[indexPath.section]["Data"]??[indexPath.row]?["Name"] as? String
Since RidesData[indexPath.section]["Data"] is AnyObject?! you have to unwrap it twice.
Why AnyObject?! ? Because RidesData[indexPath.section] is AnyObject, and AnyObject may or may not have subscript. So, the first ? means, "If it has subscript", and the second means "If subscript returns non nil".
Replace this line
let RideName = RidesData[indexPath.section]["Data"][indexPath.row]["Name"]
with this
let RideName = RidesData[indexPath.section]["Data"][indexPath.row]["Name"] as! String
RidesData[indexPath.section]["Data"] is of type AnyObject?! and then you try to access the indexPath.row element. You need to first unwrap this part.
Try this:
let RideName = RidesData[indexPath.section]["Data"]?[indexPath.row]["Name"]
The problem is with the cast, the array RidesData is an optional array: [AnyObject]?.
So you must write it like this:-
let RideName = RidesData[indexPath.section]["Data"][indexPath.row]["Name"] as! String

Is it possible to convert a JSValue into an NSNumber?

This will show the following error: 'JSValue' is not convertible to 'NSNumber'. If it's not possible to convert, how should I go about getting the JSValue and assigning it to my NSNumber variable?
var sentences:NSNumber = getSentences.callWithArguments([])
According to the header file JSValue.h, you need to call toNumber() on your JSValue object. So it's probably:
var sentences:NSNumber = getSentences.callWithArguments([]).toNumber()
You can try:
if let sentences = getSentences.callWithArguments([]) as? NSNumber {
// consume sentences here
}
The if let structure is probably the simplest access to it since it may not actually BE a number, If that doesn't work, you'll have to go back to JavaScriptCore and call JSValueToNumber:
let sentences = getSentences.callWithArguments([])
let nSentences = JSValueToNumber(context, sentences, nil)

How do I convert an NSString to an integer using Swift?

I need to convert an NSString to an integer in Swift: Here's the current code I'm using; it doesn't work:
var variable = (NSString(data:data, encoding:NSUTF8StringEncoding))
exampeStruct.otherVariable = (variable).intValue
Variable is a normal varable, and exampleStruct is a struct elsewhere in the code with a subvariable otherVariable.
I expect it to set exampleStruct.otherVariable to an int value of the NSString, but I get the following error:
"Cannot convert the expression's type () to type Float"
How do I convert an NSString to int in Swift?
It looks to me like the problem might not be the Int conversion, but rather that the exampleStruct is expecting a Float.
If that's not the issue however (and granted, Xcode errors for Swift often seem to be more about the line number rather than about the actual problem) then something like this should work for you?
var ns:NSString = "1234"
if let i = (ns as String).toInt() {
exampleStruct.otherVariable = i
}
I know you already got your answer, but I just want to explain what (I think) might not be trivial
First, we have some NSData we want to convert to NSString, because no one guaranties the data is a valid UTF8 buffer, it return an optional
var variable = NSString(data:data, encoding:NSUTF8StringEncoding)
Which means variable: NSString?
Usually NSString is bridged to swift's String, but in this case, we use an NSString constructor - you can think about it more as a "Foundation"-like syntax that wasn't directly imported to swift (as there's no bridge for NSData)
we can still use the 'Foundation' way with NSString
if let unwrappedVariable = variable {
var number = unwrappedVariable.intValue
}
if number is a Float, but the string is a string representation of an integer
if let unwrappedVariable = variable {
var number: Float = Float(unwrappedVariable.intValue)
}
if both number and the string (representation of) are floats:
if let unwrappedVariable = variable {
var number:Float = unwrappedVariable.floatValue
}
Anyway, there's a small problem with using Foundation. For these types of conversions it has no concept of an optional value (for int, float). It will return 0 if it cannot parse a string as and integer or float. That's why it's better to use swift native String:
if let variable: String = NSString(data: data, encoding: NSUTF8StringEncoding) {
if let integer = variable.toInt() {
var integerNumber = integer
var floatNumber = Float(integer)
}
}
edit/update:
No need to use NSString when coding with Swift. You can use Swift native String(data:) initializer and then convert the string to Int:
if let variable = String(data: data, encoding: .utf8),
let integer = Int(variable) {
exampeStruct.otherVariable = integer
}
If other variable is a Float type:
if let variable = String(data: data, encoding: .utf8),
let integer = Float(variable) {
exampeStruct.otherVariable = integer
}

Resources