Swift Playground - Files are not readable - xcode

Files are not readable in Swift Playground.
How to make files readable?
Same code runs well on Xcode terminal app, but fails on Swift Playground.
Demo code below.
import Foundation
println("Hello, World!")
var fname:String = "/Users/holyfield/Desktop/com.apple.IconComposer.plist"
var fm:NSFileManager = NSFileManager.defaultManager()
if(fm.fileExistsAtPath(fname)){
println("File Exists")
if(fm.isReadableFileAtPath(fname)){
println("File is readable")
var fd:NSData? = NSData(contentsOfFile: fname)
println(fd?.length)
let pl = NSDictionary(contentsOfFile: fname)
println(pl?.count)
println(pl?.allKeys)
}else{
println("File is not readable")
}
}
else{
println("File does not exists")
}
Sample images:

I have to thank Nate Cook for first for his quick response and solid answer.
Just for case I share his answer from another post, which title is misleading.
See Nate's answer here: https://stackoverflow.com/a/26723557/2360439
Playgrounds are sandboxed, so you won't be able to just grab files from anywhere in your user folder. Here's how to add that file to your
playground to make it accessible:
Find your ".playground" file in the Finder Right click and choose "Show Package Contents"
You should see "timeline.xctimeline", "contents.xcplayground", and "section-1.swift"
Make a new folder called "Resources" if it doesn't exists yet.
Copy your files into Resources folder
Seems that there is no way to access files with Swift Playground outside of Playground sandbox. If you know how to access files outside of sandbox, you are welcome to share your solution!!

There are several ways to do load files into a Swift Playground. I'll highlight the Image Literal, File Menu and Context Menu techniques.
Image Literal technique
This is the easiest and COOLEST. You simply drag a file from anywhere on your machine into the code and assign it via a let or var statement. GIF here.
File Menu technique
Choose File -> Add Files to "MyProjectName"
See GIF of this here.
Context Menu technique
You can reveal the current playground in the Xcode (7.3.1) Project Navigator using the right-click menu. Upon revealing the current playground, you'll see a directory entitled Resources. Simply drag the file you want access to into that folder and watch the magic happen (given you've written the file access code).
Example resource loading code
Here's an example of doing this for showing an image:
let url: NSURL! = NSBundle.mainBundle().URLForResource("IMG_4099", withExtension: "JPG")
let imagePath = url.path
let image = UIImage(contentsOfFile: imagePath!)
let imageView = UIImageView.init(image: image)
I've produced an animated GIF that demonstrates this in action. Here's a screengrab from that:
Reading external code
If you want to add auxiliary code in addition to resources, use the Sources folder.
A note regarding the console
The console area of Xcode's Playground interface will show you that the UIImage instance is nil when you load an image file outside the sandbox. If you entered a path you know exists, but the image isn't showing, ensure the UIImage instance isn't printing as nil.

You also can create and use Shared Playground Data folder.
Just like that:
/Users/username/Documents/Shared Playground Data/file.txt
And any file located there becomes readable to any playground!

Related

Possible encoding issues with PDFDocument

I am using PDFKit in a Mac app (Xcode 11.7, 10.15 deployment target) to view pdfs. Users are able to highlight selections and either copy the text, or create quotes.
With some pdfs, I cannot get the correct string contents for the highlight.
Take the following pdf: https://www.irs.gov/pub/irs-pdf/iw8bene.pdf. If it is opened in Preview, it is possible to copy and paste contents into TextEdit, for example.
If I open this pdf with PDFView, only some text can be copied and pasted (the main heading for example), but body text only pastes the copied spaces! I have no custom code to handle copy on my PDFView.
If I evaluate the current PDFSelection when the document is highlighted, I get spaces, and nonsense characters in the string:
for character in pdfSelection.string!.unicodeScalars {
print(character.value)
}
Example result:
32
1113109
1113135
1113135
1113109
32
1113118
1113091
32
Whatever is wrong, the standard copy code is falling foul of it too, so perhaps there is some set-up issue on PDFView or PDFDocument that I am missing? I simply create a PDFView in Interface Builder, then open a PDFDocument with a URL and set it on the view.
This issue was being caused elsewhere in my application, but still related to PDFDocument. When dragging a pdf to my app I create a PDFDocument to check validity, then save that item to the app's folder:
guard let pdf = PDFDocument(url: fileURL) else { ... }
guard pdf.write(to: documentURL(forID: documentID, andType: .pdf)) else { ... }
It was this processing of the file that caused it to be subtly modified/broken.
This was naive of me based on the complexity of pdfs. I will simply copy the original file in future.

NSOpenPanel won't close properly during Swift function

I'm a newcomer to Swift (2.2) and am having a problem with a simple app using Xcode 7.3 and OS X 10.11. In this app, the user clicks a button and selects a file through NSOpenPanel. The code uses the URL selected to get the file's data and name, then processes the data and saves the result somewhere else. With large files, the processing can take several seconds. When processing large files, once the file is selected, the space where the Open File window had been remains blank, covering the app view and everything else, and stays there until the operation is complete. Also, the app's outlets are frozen until the operation finishes. It appears NSOpenPanel isn't handing window control back to the app and the system.
The code goes like this:
#IBAction func processFile(sender: AnyObject) {
var chosenURL: NSURL?
let openPanel = NSOpenPanel()
openPanel.title = "Choose a file"
openPanel.canChooseDirectories = false
openPanel.allowsMultipleSelection = false
if openPanel.runModal() == NSFileHandlingPanelOKButton {
chosenURL = openPanel.URL
}
let dataBytes = NSData(contentsOfURL: chosenURL!)
let fileName = chosenURL!.lastPathCompnent!
// Remaining code processes dataBytes and fileName
I've tried a few variations but get the same result. Searching for "NSOpenPanel won't close" on the 'net usually just brings up examples in Objective-C, which I know nothing of. Any suggestions of how to make NSOpenPanel shut off and have view and control return to the app window?
Following on from Eric D's suggestion, I looked into Grand Central Dispatch and background processes. My first approach was:
dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0)) {
dataBytes = NSData(contentsOfURL: chosenURL!)
}
That didn't change anything. I found I had to put the whole remaining process (everything from 'let dataBytes…' onwards) within the dispatch closure, with 'dispatch_async(dispatch_get_main_queue())' statements around UI updates. This stopped the window from freezing and blanking, and returned control to the app. Thanks again, Eric.

How do I write to a file in Swfit2 from the Playground? [duplicate]

Files are not readable in Swift Playground.
How to make files readable?
Same code runs well on Xcode terminal app, but fails on Swift Playground.
Demo code below.
import Foundation
println("Hello, World!")
var fname:String = "/Users/holyfield/Desktop/com.apple.IconComposer.plist"
var fm:NSFileManager = NSFileManager.defaultManager()
if(fm.fileExistsAtPath(fname)){
println("File Exists")
if(fm.isReadableFileAtPath(fname)){
println("File is readable")
var fd:NSData? = NSData(contentsOfFile: fname)
println(fd?.length)
let pl = NSDictionary(contentsOfFile: fname)
println(pl?.count)
println(pl?.allKeys)
}else{
println("File is not readable")
}
}
else{
println("File does not exists")
}
Sample images:
I have to thank Nate Cook for first for his quick response and solid answer.
Just for case I share his answer from another post, which title is misleading.
See Nate's answer here: https://stackoverflow.com/a/26723557/2360439
Playgrounds are sandboxed, so you won't be able to just grab files from anywhere in your user folder. Here's how to add that file to your
playground to make it accessible:
Find your ".playground" file in the Finder Right click and choose "Show Package Contents"
You should see "timeline.xctimeline", "contents.xcplayground", and "section-1.swift"
Make a new folder called "Resources" if it doesn't exists yet.
Copy your files into Resources folder
Seems that there is no way to access files with Swift Playground outside of Playground sandbox. If you know how to access files outside of sandbox, you are welcome to share your solution!!
There are several ways to do load files into a Swift Playground. I'll highlight the Image Literal, File Menu and Context Menu techniques.
Image Literal technique
This is the easiest and COOLEST. You simply drag a file from anywhere on your machine into the code and assign it via a let or var statement. GIF here.
File Menu technique
Choose File -> Add Files to "MyProjectName"
See GIF of this here.
Context Menu technique
You can reveal the current playground in the Xcode (7.3.1) Project Navigator using the right-click menu. Upon revealing the current playground, you'll see a directory entitled Resources. Simply drag the file you want access to into that folder and watch the magic happen (given you've written the file access code).
Example resource loading code
Here's an example of doing this for showing an image:
let url: NSURL! = NSBundle.mainBundle().URLForResource("IMG_4099", withExtension: "JPG")
let imagePath = url.path
let image = UIImage(contentsOfFile: imagePath!)
let imageView = UIImageView.init(image: image)
I've produced an animated GIF that demonstrates this in action. Here's a screengrab from that:
Reading external code
If you want to add auxiliary code in addition to resources, use the Sources folder.
A note regarding the console
The console area of Xcode's Playground interface will show you that the UIImage instance is nil when you load an image file outside the sandbox. If you entered a path you know exists, but the image isn't showing, ensure the UIImage instance isn't printing as nil.
You also can create and use Shared Playground Data folder.
Just like that:
/Users/username/Documents/Shared Playground Data/file.txt
And any file located there becomes readable to any playground!

How to load an image in a QPixmap to display it in a QLabel

I've read multiple article on it and it still does'nt work!!
I know I'm doing it right, but for some reason it does'nt work.
Here's my code :
myIcon = new QLabel();
QPixmap myPixmapForNow;
if(!myPixmapForNow.load(":/img/Interrogation.png")){
qWarning("Failed to load");
}
myIcon->setPixmap(myPixmapForNow);
It tells me that the file failed to load each time.
What i want to do with this is to display an image that will have a tooltip and explain what the button next to it does. Basicaly, I'm looking for a way to display an image that have a tooltip programmed in it.
I'm a beginner and honestly the concept of looking in folders is a bit abstract for me. If you have a blog or something to propose, i'll be willing to read it. I've been looking for one and I have'nt found any good one that explain the concept and how to do it.
If you have a solution for my problem please explain it. Nothing better than explanation :)
Thanks
Two things to do:
Check if QFile can open that resource and read it. Dump it out to a file on disk.
QFile fi(":/img/Interrogation.png");
QFile fo(QDir::homePath() + QDir::separator() + "Interrogation.png");
if (!fi.open(QIODevice::ReadOnly)) {
qWarning() << "Can't open the resource" << fi.fileName();
return;
}
if (!fo.open(QIODevice::WriteOnly)) {
qWarning() << "Can't open the output" << fo.fileName();
return;
}
fo.write(fi.readAll());
Check the format of whatever is dumped out to disk to ensure that it's a valid png file. You can open it in an image editor, for example - just be sure to verify that the extension agrees with the contents. A valid JPEG file with .png extension will fail to load.
Seems, I've reproduced your error. Probably, you are missed default prefix of resources that QtCreator usually sets up into "/new/prefix1/". This string prefix must exist due to access resources. Try to modify your code within following way:
if(!myPixmapForNow.load(":/new/prefix1/img/Interrogation.png")){
Or, you need to discover your resource file to find out proper prefix string. If you had already modified prefix string then modify your code correspondently.

How to create a generic file selection dialog in QT4 for Windows

I have been searching for clues on this issue for some time now, with no results. So, here goes...
I have an application that I want to have a simple button to open a file dialog window. There are other buttons on the main window that will read or create/write the file (after doing the appropriate checks for the function selected). I used to use the QFileDialog::getSaveFileName() function without issues, but with Windows 7, this fails if the file exists AND is read-only. I switched to the getOpenFileName() to get around this issue, but now the file dialog fails if the user tries to select a non-existent file (irrelevant on a save operation).
Is there a way to add a "Create New File" icon to the file dialog, or add it to the right-click menu within the file dialog window? I would really hate to have to rewrite the app just because of (yet another) Windows behavior change.
QFileDialog::getOpenFileName() should only be used for opening existing files. If you type in a name of a file that doesn't exist and the system complains, this is proper behaviour. It's correctly telling you that you can't open a file that doesn't exist.
If you want to write to an existing file or create a new file, you should be using QFileDialog::getSaveFileName()
If you're trying to write to an existing file that is marked as Read-Only in the operating system and you get an error saying that the file is Read-Only, then the error is correct. You should not be allowed to write to a read-only file, that's just what Read-Only means.
From what you've explained, there are no errors here. Everything's happening as it should be. If you're trying to force the system to do something different, don't. You should rather try and think of doing things a different way.
Ok, since this was never really answered here, and I have since figured out a solution, I thought I would update this with the code snippet I am using.
void MainWindow::on_tbBrowse_clicked()
{
// Use the location of already entered file
QString fileLocation = leFile->text();
QFileInfo fileinfo(fileLocation);
// See if there is a user-defined file extension.
QString fileType = qgetenv("DiskImagerFiles");
if (fileType.length() && !fileType.endsWith(";;"))
{
fileType.append(";;");
}
fileType.append(tr("Disk Images (*.img *.IMG);;*.*"));
// create a generic FileDialog
QFileDialog dialog(this, tr("Select a disk image"));
dialog.setNameFilter(fileType);
dialog.setFileMode(QFileDialog::AnyFile);
dialog.setViewMode(QFileDialog::Detail);
dialog.setConfirmOverwrite(false);
if (fileinfo.exists())
{
dialog.selectFile(fileLocation);
}
else
{
dialog.setDirectory(myHomeDir);
}
if (dialog.exec())
{
// selectedFiles returns a QStringList - we just want 1 filename,
// so use the zero'th element from that list as the filename
fileLocation = (dialog.selectedFiles())[0];
if (!fileLocation.isNull())
{
leFile->setText(fileLocation);
QFileInfo newFileInfo(fileLocation);
myHomeDir = newFileInfo.absolutePath();
}
setReadWriteButtonState();
updateHashControls();
}
}
setReadWriteButtonState() will enable the buttons according to the file state:
if file is read-only, only Read button is enabled
if file doesn't exist, only Write button is enabled
The entire code is available for others to review at https://sourceforge.net/projects/win32diskimager/. I hope this helps the next person that is looking for a solution to this. Just please include attribution if you use our code.

Resources