Trouble creating CFAttributedString after upgrade to Xcode 6.3 with Swift - xcode

My code, that draws an CFAttributedString into a graphic context, used to work fine before the update to Xcode 6.3.
Now, after the upgrade, I get the following errors:
'_' is not convertible to 'CFString!'
and
'[String : AnyObject]' is not convertible to '[String : AnyObject]'
for the lines of code that define the attributes for the string:
let attributes : [String:AnyObject] = [
kCTForegroundColorAttributeName:UIColor.darkGrayColor().CGColor,
kCTFontAttributeName:font
]
This is how I draw the text:
var attrString = CFAttributedStringCreate(nil,myString,attributes)
var line = CTLineCreateWithAttributedString(attrString)
var lineWidth = CTLineGetBoundsWithOptions(line, CTLineBoundsOptions.UseGlyphPathBounds).width
var lineHeight = CTLineGetBoundsWithOptions(line, CTLineBoundsOptions.UseGlyphPathBounds).height
CGContextSetTextMatrix(context, transformScale)
CGContextSetTextPosition(context, (rect.width - lineWidth)/2, rect.height - lineHeight*1.5)
CTLineDraw(line, context)
I tried to cast kCTForegroundColorAttributeName and kCTFontAttributeName with adding "as String" after them. This removed the errors but the strings didn't seem to get the attributes.

I solved the problem by changing the formatting and by replacing kCTForegroundColorAttributeName with NSForegroundColorAttributeName
Here is the fixed line:
let attributes: [String: AnyObject] = [
NSForegroundColorAttributeName : UIColor.darkGrayColor().CGColor,
NSFontAttributeName : font
]

Related

Adding different alignment and font size to different lines in one TextLabel in TableCell swift

so i'm trying to implement a simple english to farsi dictionary in iOS
i'd like to include both words in one table cell, problem is that english is L>R and farsi is R>L, also i'd like to make the farsi word a bit bigger.
I created an AttributedMutableString and I thought I put down all the correct values but it looks like there is a problem since it isn't rendering correctly.
code:
cell.textLabel?.numberOfLines = 0
var myString = "\(englishConvo[indexPath.row])\n\(farsiConvo[indexPath.row])"
var mutableString = NSMutableAttributedString()
var lenOfLang1 = englishConvo[indexPath.row].characters.count
var lenOfLang2 = farsiConvo[indexPath.row].characters.count
let increaseFontSize = UIFont(name: (cell.textLabel?.font.fontName)!, size: (cell.textLabel?.font?.pointSize)! + 5)
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = NSTextAlignment.Right
mutableString = NSMutableAttributedString(string: myString)
mutableString.addAttribute(NSParagraphStyleAttributeName, value: paragraphStyle, range: NSRange(location: lenOfLang1 + 1, length: lenOfLang2))
mutableString.addAttribute(NSFontAttributeName, value: increaseFontSize!, range: NSRange(location: lenOfLang1 + 1, length: lenOfLang2))
cell.textLabel?.attributedText = mutableString
If i convert to a string using this code this is what I get
cell.textLabel?.text = String(mutableString)
Any thoughts / ideas would be super appreciated
Table cells already come with a layout that gives you two labels (text and detail), so why not just use it? Here, for example, in a language app of mine, I'm displaying a Latin word in the text label and an English translation in the detail label. You could easily do the same with Farsi and English.

Swift Error: Cannot find an initializer for type 'Double' that accepts an argument list of type '(String)'

I am trying to grab data from a text field labeled 'temperatureTextField' and assigning it to 't' which is a Double. Ideally the user is meant to add a number value to the temperatureTextField.
Here is my method:
#IBOutlet weak var temperatureTextField: UITextField!
#IBAction func convert(sender: AnyObject) {
let t = Double(temperatureTextField.text!)
let tempM = TemperatureModel(temp: t!)
temperatureTextField.text = String(tempM.toCelsius())
}
The red exclamation is coming from the line "let t = Double(temperatureTex...)"
You're probably using Xcode 6, so Swift 1.2, but the String initializer for Double is only available in Swift 2 (Xcode 7).
You can always use NSString's doubleValue property:
let t = (temperatureTextField.text! as NSString).doubleValue
but I'd recommend using Xcode 7 and Swift 2 as soon as possible.
As Eric suggested, I ran into this issue because I was running an outdated version of xcode.
Here is what my code looked liked after, in case anyone runs into trouble and is unable to update:
let t = (inputText.text! as NSString).doubleValue
let tempModel = TemperatureModel(temp: t)
inputText.text = "\(tempModel.toCelsius())"

Strange error when adding UIFont to styling dictionary (NSAttributedString) [duplicate]

let timeFont = [NSFontAttributeName:UIFont(name: "Voyage", size: 20.0)]
var attrString3 = NSAttributedString("(Time)", attributes : timeFont); // <--- compiler error "Extra argument in call"
This code worked in xcode 6.0, but now that I've upgraded to xcode 6.1 it doesn't work anymore and I can't figure out what I need to get it back working. It says that there is an extra argument, but that's not correct. I believe that it has something to do with the new failable initializers, but everything that I've tried doesn't' work.
There are two reasons your code is failing to compile:
The initializer for NSAttributedString that you want to use now requires the explicit labeling of the string parameter
The UIFont initializer that you are using now returns an optional (i.e., UIFont?), which needs to be unwrapped before you pass it in the attributes dictionary.
Try this instead:
let font = UIFont(name: "Voyage", size: 20.0) ?? UIFont.systemFontOfSize(20.0)
let attrs = [NSFontAttributeName : font]
var attrString3 = NSAttributedString(string: "(Time)", attributes: attrs)
Note the use of the new coalescing operator ??. This unwraps the optional Voyage font, but falls back to the System Font if Voyage is unavailable (which seems to be the case in the Playground). This way, you get your attributed string regardless, even if your preferred font can't be loaded.
Xcode 6.1 comes with Swift 1.1 that supports constructors that can fail. UIFont initialisation can fail and return nil. Also use string: when creating NSAttributedString:
if let font = UIFont(name: "Voyage", size: 20.0) {
let timeFont = [NSFontAttributeName:font]
var attrString3 = NSAttributedString(string: "(Time)", attributes : timeFont)
}

Binary operator '+' cannot be applied to two CGFloat operands?

Coding in Swift and get the above error...
Is the message masking something else OR can you really not add two CGFloat operands? If not, why (on earth) not?
EDIT
There is nothing special in the code I am trying to do; what is interesting is that the above error message, VERBATIM, is what the Swift assistant compiler tells me (underlining my code with red squiggly lines).
Running Xcode 6.3 (Swift 1.2)
It's absolutely possible, adding two CGFloat variables using the binary operator '+'. What you need to know is the resultant variable is also a CGFloat variable (based on type Inference Principle).
let value1 : CGFloat = 12.0
let value2 : CGFloat = 13.0
let value3 = value1 + value2
println("value3 \(value3)")
//The result is value3 25.0, and the value3 is of type CGFloat.
EDIT:
By Swift v3.0 convention
let value = CGFloat(12.0) + CGFloat(13.0)
println("value \(value)")
//The result is value 25.0, and the value is of type CGFloat.
I ran into this using this innocent-looking piece of code:
func foo(line: CTLine) {
let ascent: CGFloat
let descent: CGFloat
let leading: CGFloat
let fWidth = Float(CTLineGetTypographicBounds(line, &ascent, &descent, &leading))
let height = ceilf(ascent + descent)
// ~~~~~~ ^ ~~~~~~~
}
And found the solution by expanding the error in the Issue Navigator:
Looking into it, I think Swift found the +(lhs: Float, rhs: Float) -> Float function first based on its return type (ceilf takes in a Float). Obviously, this takes Floats, not CGFloats, which shines some light on the meaning of the error message. So, to force it to use the right operator, you gotta use a wrapper function that takes either a Double or a Float (or just a CGFloat, obviously). So I tried this and the error was solved:
// ...
let height = ceilf(Float(ascent + descent))
// ...
Another approach would be to use a function that takes a Double or CGFloat:
// ...
let height = ceil(ascent + descent)
// ...
So the problem is that the compiler prioritizes return types over parameter types. Glad to see this is still happening in Swift 3 ;P
Mainly two possible reasons are responsible to occur such kind of error.
first:
Whenever you try to compare optional type CGFloat variable
like
if a? >= b?
{
videoSize = size;
}
This is responsible for an error so jus make it as if a! >= b!{}
Second:
Whenever you direct use value to get a result at that time such kind of error occure
like
var result = 1.5 / 1.2
Don't use as above.
use with object which is declare as a CGFloat
like
var a : CGFloat = 1.5
var b : CGFloat = 1.2
var result : CGFloat!
result = a / b

Swift UITextChecker

I am trying to use UITextChecker in my Swift project. The code below currently has an error on the last line:
var checker:UITextChecker = UITextChecker()
var textLength = countElements(textView.text)
var checkRange:NSRange = NSMakeRange(0, textLength)
var misspelledRange:NSRange = checker.rangeOfMisspelledWordInString(textView.text, range: checkRange, startingAt: checkRange.location, wrap: false, language: "en_Us")
var arrGuessed:NSArray = checker.guessesForWordRange(misspelledRange, inString: textView.text, language: "en_US")!
var correctedStr = textView.text.stringByReplacingCharactersInRange(misspelledRange, withString: [arrGuessed.objectAtIndex(0)])
The error says:
'NSRange' is not convertible to 'Range<String.index>'
I am not sure where I am going wrong.
Thanks
The stringByReplacingCharactersInRange method you're using expects Range<String.Index> to be passed in, not NSRange. You can't use misspelledRange because it's the wrong type. The link in the possible duplicate comment (NSRange to Range<String.Index>) has examples of deriving a Range<String.Index> from an NSRange or casting text to NSString, whose stringByReplacingCharactersInRange method does use NSRange.

Resources