Cocoa NSAttributedString Pasting Changes Font - cocoa

I have an NSAttributedString which has an NSAttachment and some text. I have copied it to the pasteboard. I have also made sure that the string has no font attributes. When I paste it, it always changes the font to Helvetica. Is there any way to prevent this behavior?
let wrapper = NSFileWrapper()
wrapper.preferredFilename = "image"
let attachment = NSTextAttachment(fileWrapper: wrapper)
if let im = NSImage(data: data) { attachment.image = im }
let image = NSAttributedString(attachment: attachment)
let str = NSMutableAttributedString(attributedString: image)
str.appendAttributedString(NSAttributedString(string: "hello world"))
let range = NSMakeRange(0, str.length)
//remove font attributes
str.removeAttribute(NSFontAttributeName, range: range)
str.removeAttribute(NSFontSizeAttribute, range: range)
Swift.print(str.attributes) //prints an empty array
At this point I copy the data to the clipboard
if let d = str.RTFDFromRange(range, documentAttributes: [NSDocumentTypeDocumentAttribute: NSRTFDTextDocumentType]) {
let pboard = NSPasteboard.generalPasteboard()
pboard.clearContents()
pboard.declareTypes([NSPasteboardTypeRTFD], owner: self)
pboard.setData(d, forType: NSPasteboardTypeRTFD)
}

Related

How to use an array to fill the title text

I've created a customized keyboard using UIView. I'm trying to auto-fill the letters using a for loop but with no success.
func initializeSubviews() {
let xibFileName = "keyboardView" // xib extension not included b
let view = Bundle.main.loadNibNamed(xibFileName, owner: self, options: nil)![0] as! UIView
self.addSubview(view)
view.frame = self.bounds
setKeyboardText()
}
#IBOutlet var keyboardLetters: [myKeyboardBtn]!
func setKeyboardText() {
let str = "abcdefghijklmnopqrstuvwxyz"
let characterArray = Array(str)
for (Index, key) in keyboardLetters.enumerated() {
key.titleLabel?.text = String(characterArray[Index])
}
// [a,b,c,d,...]
}
what am I doing wrong?
According to Apple
"To set the actual text of the label, use setTitle(_:for:)
(button.titleLabel.text does not let you set the text)."

SceneKit Swift3 compiler-error

I'm trying to run animated "DAE" model in SceneKit:
let url = Bundle.main.url(forResource: "art.scnassets/Player(walking)", withExtension: "dae")
let sceneSource = SCNSceneSource(url: url!, options: [SCNSceneSource.LoadingOption.animationImportPolicy: SCNSceneSource.AnimationImportPolicy.playRepeatedly] )
let animationIds: NSArray = sceneSource?.identifiersOfEntries(withClass: CAAnimation)
for eachId in animationIds {
let animation: CAAnimation = (sceneSource?.entryWithIdentifier(eachId as! String, withClass: CAAnimation.self))!
animations.add(animation)
}
character?._walkAnimations = animations
But compiler It throws on the line:
let animationIds: NSArray = sceneSource?.identifiersOfEntries(withClass: CAAnimation)
and writes an error:
Cannot convert value of type '[String]?' to specified type 'NSArray'
Please help me to fix that problem.
Thanks in advance.
Why you are converting [String]? to NSArray and then convert each element to String again, no need of it simply use Swift native Array and wrapped the optional value with if let or guard let.
guard let animationIds = sceneSource?.identifiersOfEntries(withClass: CAAnimation) else {
return
}
for eachId in animationIds {
if let animation = sceneSource?.entryWithIdentifier(eachId, withClass: CAAnimation.self) {
animations.add(animation)
}
}
character?._walkAnimations = animations

How to save and load file image by swift

I have UIImage (got from Parse - convert variable PFFile).
How can I save and load image from this variable?
let a = object["image"] as! PFFile
a.getDataInBackgroundWithBlock({ (data:NSData?, error:NSError?) -> Void in
if (error == nil) {
// I have image, but the next I don't know what I do
let image = UIImage(data:data!)
}
})
Save image png
func saveImage(image:UIImage,name:String){
let selectedImage: UIImage = image
let data:NSData = UIImagePNGRepresentation(selectedImage)
let path = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
let success = fileManager.createFileAtPath(path, contents: data, attributes: nil)
print(success)
// Check image saved successfully
let getImagePath = (path as NSString).stringByAppendingPathComponent(name)
if fileManager.fileExistsAtPath(getImagePath) {
// image save success
let image = UIImage(contentsOfFile: getImagePath)!
}
else{
// image save error
}
}
Save other file
static func saveFile(fileData:NSData,name:String)->Bool{
let success = NSFileManager.defaultManager().createFileAtPath(path+"/"+name, contents: fileData, attributes: nil)
return success
}

Reading a RTF file and parse plaintext

I am doing this to get the content of a file using NSOpenPanel, but I am getting a lot of weird stuff returned from the .rtf file I select.
My panel code:
var panel: NSOpenPanel = NSOpenPanel()
var fileTypesArray: NSArray = ["txt", "rtf", "nil"]
panel.canChooseFiles = true
panel.allowedFileTypes = fileTypesArray as [AnyObject]
panel.allowsMultipleSelection = false
if panel.runModal() == NSModalResponseOK {
var url = panel.URL!.path
println(url)
let path = url
let expandedPath = path!.stringByExpandingTildeInPath
let data: NSData? = NSData(contentsOfFile: expandedPath)
if let fileData = data {
let content = NSString(data: fileData, encoding:NSUTF8StringEncoding) as! String
println(content)
}
}
The contents of my .rtf document is "Testing 123"
This is what is being printed to the console:
{\rtf1\ansi\ansicpg1252\cocoartf1347\cocoasubrtf570
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\paperw11900\paperh16840\margl1440\margr1440\vieww10800\viewh8400\viewkind0
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural
\f0\fs24 \cf0 Testing 123\
}
Is there any way I can get just the text from the file, and what is all the other stuff that is being printed?
That "other stuff" is the actual RTF data.
I would recommend using the NSAttributedString initializer NSAttributedString(path:documentAttributes:), which will read in and process the RTF data. Then you can access the plain text by using attributedString.string.
In your case, it would be
if let content = NSAttributedString(path: expandedPath, documentAttributes: nil) {
// do something with content or content.string
}

set and create paragraph style in swift

I am trying to port an objective C method to draw text in a PDF context to Swift.
I could convert most of the code, but the following lines are giving me a problem.
Some help in the conversion would be welcome.
Here the Objective C code:
-(void)drawText:(NSString *)textToDraw context:(CGContextRef)myPDFContext textcolor:(NSColor *)textcolor textfont:(NSFont*)textfont textbox:(CGRect)boxsize pagesize:(CGSize)pageSize {
// .........
// create paragraph style and assign text alignment to it
CTTextAlignment alignment = kCTJustifiedTextAlignment;
CTParagraphStyleSetting _settings[] = { {kCTParagraphStyleSpecifierAlignment, sizeof(alignment), &alignment} };
CTParagraphStyleRef paragraphStyle = CTParagraphStyleCreate(_settings, sizeof(_settings) / sizeof(_settings[0]));
// set paragraph style attribute
CFAttributedStringSetAttribute(attrStr, CFRangeMake(0, CFAttributedStringGetLength(attrStr)), kCTParagraphStyleAttributeName, paragraphStyle);
// .........
}
// The following lines are my try in Swift, but this gives errors:
func DrawText(textToDraw:String, myPDFContext:CGContextRef, textcolor:NSColor, textfont:NSFont, boxsize:CGRect, pagesize:CGSize) {
var alignment = CTTextAlignment.TextAlignmentLeft
let alignmentSetting = CTParagraphStyleSetting(spec: CTParagraphStyleSpecifier.Alignment, valueSize: sizeof(alignment), value: &alignment)
let paragraphStyle = CTParagraphStyleCreate(alignmentSetting, 1)
//.......
If this is solved I could post the complete method in Swift.
I think this does it:
var alignment = CTTextAlignment.TextAlignmentLeft
let alignmentSetting = [CTParagraphStyleSetting(spec: .Alignment, valueSize: UInt(sizeofValue(alignment)), value: &alignment)]
let paragraphStyle = CTParagraphStyleCreate(alignmentSetting, 1)
CFAttributedStringSetAttribute(attrStr, CFRangeMake(0, CFAttributedStringGetLength(attrStr)), kCTParagraphStyleAttributeName, paragraphStyle)
I made the following modifications:
I changed sizeof(alignment) to UInt(sizeofValue(alignment)) because sizeof in Swift only takes a type (such as sizeof(Int)). The UInt() is a constructor that turns the Int returned by sizeofValue into the UInt needed by this call.
I make alignmentSetting into an array so that it could be passed to an UnsafePointer of that type. This also better matches the original version.
I changed CTParagraphStyleSpecifier.Alignment to just .Alignment since the first part isn't needed since spec is of type CTParagraphStyleSpecifier.
The hardcoded 1 is OK in this case because you are passing just one value, but the more general solution would be to do:
let paragraphStyle = CTParagraphStyleCreate(alignmentSetting, UInt(alignmentSetting.count))
Here the full working method based on the corrections and help.
func drawText(textToDraw:String, myPDFContext:CGContextRef, textcolor:NSColor, textfont:NSFont, boxsize:CGRect, pagesize:CGSize) {
let _font = NSFont(name:textfont.fontName, size:textfont.pointSize )
if (_font == nil) {
println("Font [\(textfont)] does not exist")
return
}
let myBoxWidth = boxsize.size.width
let myBoxHeight = boxsize.size.height
let myBoxxpos = boxsize.origin.x
let myBoxypos = boxsize.origin.y
let frameRect = CGRectMake(myBoxxpos, myBoxypos,myBoxWidth,myBoxHeight);
let framePath = CGPathCreateMutable()
CGPathAddRect(framePath, nil, frameRect);
// create attributed string
let attrStr = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);
CFAttributedStringReplaceString (attrStr, CFRangeMake(0, 0), textToDraw);
// create font
let font = CTFontCreateWithName(textfont.fontName, textfont.pointSize, nil);
var alignment = CTTextAlignment.TextAlignmentLeft
let alignmentSetting = [CTParagraphStyleSetting(spec: .Alignment, valueSize: UInt(sizeofValue(alignment)), value: &alignment)]
//let paragraphStyle = CTParagraphStyleCreate(alignmentSetting, 1)
let paragraphStyle = CTParagraphStyleCreate(alignmentSetting, UInt(alignmentSetting.count))
CFAttributedStringSetAttribute(attrStr, CFRangeMake(0, CFAttributedStringGetLength(attrStr)), kCTParagraphStyleAttributeName, paragraphStyle)
// set font attribute
CFAttributedStringSetAttribute(attrStr, CFRangeMake(0, CFAttributedStringGetLength(attrStr)), kCTFontAttributeName, font);
// set color attribute
CFAttributedStringSetAttribute(attrStr,CFRangeMake(0, CFAttributedStringGetLength(attrStr)), kCTForegroundColorAttributeName,textcolor.CGColor);
// Prepare the text using a Core Text Framesetter.
let framesetter = CTFramesetterCreateWithAttributedString(attrStr);
// Get the frame that will do the rendering.
let currentRange = CFRangeMake(0, 0);
let frameRef = CTFramesetterCreateFrame(framesetter, currentRange, framePath, nil);
// Put the text matrix into a known state. This ensures
// that no old scaling factors are left in place.
CGContextSetTextMatrix(myPDFContext, CGAffineTransformIdentity);
// Draw the frame.
CTFrameDraw(frameRef, myPDFContext);
}

Resources