How to convert PFObject array in image view? - xcode

Sorry guys I want to try this again just reword it so its understandable.
ImageFiles is an array of PFObjects, about 10 images
let randomNumber = imageFiles[Int(arc4random_uniform(UInt32(imageFiles.count)))]
println(randomNumber)
and the println gives me a random image file from the array.
How do I put that into the image view? Meaning i want a random element of the array to be viewable in the uiimage view.
let image = UIImage(data: randomNumber as AnyObject as! NSData)
closest I've got... no syntax error only runtime
Could not cast value of type 'PFObject' (0x105639070) to 'NSData' (0x106c97a48).

An actual image stored in Parse is not of the format PFObject, it is of the type PFFile. Normally a reference to a PFFile is stored within a PFObject.
I can imagine your code/pseudocode will end up looking like the following:
let myRandomImageMetaData = imageFiles[Int(arc4random_uniform(UInt32(imageFiles.count)))]
let imageFileReference: PFFile = myRandomImageMetaData["imgLink"]
The actual code will depend on your database structure which I've already asked you for here, but you never provided.
Now that you have the file reference, then you actually have to download the image data itself. You can do it like so:
imageFileReference.getDataInBackgroundWithBlock {
(imageData: NSData?, error: NSError?) -> Void in
if error == nil {
if let imageData = imageData {
let image = UIImage(data:imageData)
}
}
}
You can read more about storing and retrieving images stored as PFFile in Parse here:
https://parse.com/docs/ios/guide#files-images
Now, your next problem is that you have not known all of this while uploading the images in the first place. So there is a high risk that you've uploaded the images to Parse badly in the first place and that the images doesn't exist there at all.

Related

Cocoa Converting RTFD to ASCII and back

Is it possible to convert an NSattributedString with attachments (RTFD not RTF) to ASCII, edit the stream, and convert it back? So far I am able to convert an RTFD to a String stream. But turning it back into an NSData object does not work. Here's the code I'm using in a playground.
import Cocoa
func stream(attr: NSAttributedString) -> String? {
if let d = attr.rtfd(from: NSMakeRange(0, attr.length), documentAttributes: [NSDocumentTypeDocumentAttribute: NSRTFDTextDocumentType]) {
if let str = String(data: d, encoding: .ascii) { return str }
else {
print("Unable to produce RTFD string")
return nil
}
}
print("Unable to produce RTFD data stream")
return nil
}
if let im = NSImage(named: "image.png") {
let a = NSTextAttachment()
a.image = im
let s = NSAttributedString(attachment: a)
if let str = stream(attr: s) {
print("\(str)\n") //prints a string, which contains RTF code combined with NSTextAttachment string representation
if let data = str.data(using: .ascii) { //this is where things stop working
if let newRTF = NSAttributedString(rtfd: data as Data, documentAttributes: nil) {
print(newRTF)
}
else { print("rtfd was not created") }
}
else { print("could not make data") }
}
}
What am I missing? Or is my entire concept wrong here? I am doing this to get around a limitation of the way OS X handles images attached in RTF documents.
Edit:
The limitation I am trying to address is to set the size of an image in an RTF stream. The text handling system requires that we use NSTextAttachment. Whenever an image is pasted from that, it automatically sizes the image to whatever the pixel height and width are. Unfortunately there is no way to control this property. I have tried here and also using all the techniques here.
As far as the ASCII stream, I'm not trying to edit the image attachment itself. When the stream is printed, the actual RTF code is visible and editable. This works and would be a good workaround for this limitation. All I need is to edit the RTF code and change the \width and \height properties that Apple uses.
After your edit I can see what you are trying to do, interesting idea, but it won't work - at least not easily.
Take a look at the value of d, it is not an ASCII string stored as a value of type Data (or NSData). It is a serialised representation of multiple items; the RTF stream (text), the image data (binary). If you convert this to an ASCII string and back again it is not going to work, you can't represent arbitrary binary data as ASCII unless you encode it (e.g. something like base 64 encoding).
Now you could attempt what you are trying a slightly different way, skip the conversion to ASCII and edit the Data value directly. That is certainly possible, but as you are editing a format you don't know (the serialised representation) you would have to be careful... And even if you succeed in editing the representation there is no guarantee that converting back to an NSAttributedString with an NSTextAttachment will preserve your edits.
I suggest you tackle this another way. You have an NSAttributedString and you don't like the RTF produced after you write this to a file. So edit the RTF after it is written, e.g. open up the RTFD package, open the contained RTF file (TXT.rtf), edit it, write it back.
HTH

Folder of images: create and fill SKShapeNodes, 1 of each

Is it possible to create a folder and have SpriteKit go through that folder, find each image (regardless of name), and create a SKShapeNode for each in that folder (regardless of how many there are)?
Assume all images are the same size, and all .png files ready to be used as unique images as textures for filling SKShapeNodes, and that all SKShapeNodes will be the same size.
I want to know, once done, how many shapes have been created, and have them uniquely named based on the name of the image of the texture used.
But all I'm reading seems to be about knowing how many images are there, and what their names are, before hand.
Clueless as to where to start searching about how to do this.
Update: no idea how to reference the "folder" with images:
I've dumped the images, with their very imaginative names [one, two, three, four, five etc. ], into a folder as "atlas", like this:
but as per Allessandro's wonderful answer, I have no idea how to address this "folder" and get at what's in it.
I think it's this line I'm getting completely wrong:
let folderPath = Bundle.main.path(forResource: "Images", ofType: nil)
I don't know what to replace "Images" with.
Update 2:
Found a much easier way to do this:
let myTextureAtlas = SKTextureAtlas(named: "demoArt")
print(myTextureAtlas)
print(myTextureAtlas.textureNames)
Too many requests , so I try to help you with some code:
Create a folder:
func createDir(folderName:String) {
let fileManager = FileManager.default
if let directory = fileManager.containerURL(forSecurityApplicationGroupIdentifier: "APP_GROUP_IDENTIFIER") {
let newDirectory = directory.appendingPathComponent(folderName)
try! fileManager.createDirectory(at: newDirectory, withIntermediateDirectories: false, attributes: nil)
}
}
Now you have your folder so you can decide to save a file or to copy one file from documents to this new directory. I make an example for the last one.
Copy a file:
let fileManager = FileManager.default
do {
try fileManager.copyItem(atPath: "hero.png", toPath: "subfolder/hero.swift")
}
catch let error as NSError {
print("Something went wrong: \(error)")
}
Now you want to know how to extract all files from a directory.
Extract all files from a directory:
func extractAllFile(atPath path: String, withExtension fileExtension:String) -> [String] {
let pathURL = NSURL(fileURLWithPath: path, isDirectory: true)
var allFiles: [String] = []
let fileManager = FileManager.default
if let enumerator = fileManager.enumerator(atPath: path) {
for file in enumerator {
if #available(iOS 9.0, *) {
if let path = NSURL(fileURLWithPath: file as! String, relativeTo: pathURL as URL).path
, path.hasSuffix(".\(fileExtension)"){
allFiles.append(path)
}
} else {
// Fallback on earlier versions
}
}
}
return allFiles
}
Usage:
let folderPath = Bundle.main.path(forResource: "Images", ofType: nil)
let allPngFiles = extractAllFile(atPath: folderPath!, withExtension: "png") // returns file path of all the png files inside the folder
After that, you can create an array of SKShapeNode based from allPngFiles using fillTexture with a SKTexture created from each image and give to each node the name of the file used (so you know at the end also how many nodes you have created from array.count).
Slightly different answer here. I'm not sure why one needs to create a directory and copy files over. In your screenshot you have a demoArt.atlas with 7 files (one.png, two.png, etc). You indicate you want to generate an SKShapeNode. It still isn't clear to me why you want SKShapeNode, but ignoring that, you just need to know the folder name. You'll notice how the folder is blue, which means it is a reference. This means that in the image, the folder is retained.
This would get you all the files in that directory:
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let texPath = NSURL(fileURLWithPath: documentsPath).appendingPathComponent("demoArt.atlas")
let filemanager:FileManager = FileManager()
// Error check/ensure path exists
let files = filemanager.enumerator(atPath:texPath!.path)
while let file = files?.nextObject() {
print(file)
// Create your SKShapeNode here, you can load file from this
// This is all relative path, so "file" would be one.png, two.png, etc. If you need the full path, you
// need to prepend texPath
}
Note the key diff here is not copying files over. Maybe I just don't understand the problem and why it would require the copy.
If you wanted to put that in an array you can. But here you'll have the file name of the texture which you would of course need to load.
Realistically, you want to load those textures asynchronously first, then construct your SKShapeNode.

Photo changing every day(Xcode, Swift)

I haven't write code for this But I want some help that can it be possible to code so that it shows new photo everyday. for example I have 10 images and I want to display each image for like September 16,17,18, and so on ?
Here you go...
Call method getImageForToday() where ever you want to fetch image for today (This solution will work specific to your case, i.e. as you mentioned you have 10 images)
func getImageForToday() -> UIImage
{
let arrImages = ["image1.png", "image2.png" ... "image10.png"]
var imageName = arrImages[getLastCharacterFromTodayDate()]
return UIImage(named: imageName)
}
func getLastCharacterFromTodayDate() -> Int
{
let calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
let component = calendar.components(NSCalendarUnit.CalendarUnitDay, fromDate: NSDate())
return component.day % 10
}
You can use the object NSDate to know what day is it and after that doing something.
First you have your dictionnary of image like that :
let images = [ UIImage(named: "image1.png")!, UIImage(named: "image2.png")!, UIImage(named: "image3.png")]
so now, you must know what day is it for the first app openning in exemple.
So you can do that :
let date = NSDate()
You put the element date in UserDefaults. (in order to save it)
You can now display a image. You make a random number and you take UIImage at this random position.
The day after, or the next app opening you recheck the NSDate with the NSDate saved and if it's different you take a other photo.

How do I make a CGImage into a 1 bit per pixel PNG file on OS X using CoreGraphics?

I've been struggling all week with this one. My first few attempts landed me with RGBA images from a monochrome image. I've gotten down to 8bit gray scale. But I need more compression. Indexed is the way to go but I have found no sample code or documentation (and I've looked) to do it. I've already asked on the Apple Developer Forums and came up blank so far.
I'm using Swift 1.2 in Xcode 6.3.1 targeting OS X 10.10. Here is a relevant section of code.
func createBitmapContext (size: CGRect) -> CGContext! {
let context = CGBitmapContextCreate(nil,
Int(size.width),
Int(size.height),
8,
0,
CGColorSpaceCreateDeviceGray(),
CGBitmapInfo(CGImageAlphaInfo.None.rawValue))
CGContextSetInterpolationQuality(context, kCGInterpolationNone)
CGContextSetShouldAntialias(context, false)
return context
}
func createCGImage(ci: CIImage) -> CGImage? {
let contextOptions = [kCIContextOutputColorSpace: NSNull(),
kCIContextWorkingColorSpace: NSNull(),
kCIContextUseSoftwareRenderer: true]
let cgContext = createBitmapContext(ci.extent())
let context = CIContext(CGContext: cgContext, options: contextOptions as [NSObject : AnyObject])
CGContextDrawImage(cgContext, ci.extent(), context.createCGImage(ci, fromRect: ci.extent()))
return CGBitmapContextCreateImage(cgContext)
}
func saveImage(path: String, image: NSData) {
image.writeToFile(path, atomically: true)
}
func getImageFileData(image: CGImage) -> NSData? {
var pngDataRef = CFDataCreateMutable(nil, 0)
let pngDest = CGImageDestinationCreateWithData(pngDataRef, kUTTypePNG, 1, nil)
CGImageDestinationAddImage(pngDest, image, nil)
CGImageDestinationFinalize(pngDest)
return pngDataRef
}
The code takes a CIImage that is already B&W. It gets rendered into a supported context to create a gray scale CGImage. I have not found a way to create an Indexed context. The image destination is an NSData object because I want to do some work with it before I spit it out to a file. The NSData object contains the file data as it will appear on disk.
What I want is an indexed image that is one bit per pixel. I know that PNG supports that format and that OS X will read it. I just haven't figured out how to create it.
Help much appreciated. Thanks.

Swift coding generate random number and link to image and sound

I am very new to both programming and swift (please be kind!). I have a working example of how to generate a random image (by assigning a number and using Int(arc4random_uniform(x)). However I do not know how I can say if this image is shown, then assign this sound to the button. Every time an image is displayed it will have a matching sound to go with it. With my limited experience I can only think of doing long winded if statements?
Answer
Pass the name of the image to a NSMutableString, without the extension (.png, or just remove the extension.). Then (hopefully the audio file has the same name as the images name) you can now call the audio file with from the mutableString.
Explanation
For Example. If you have an image named Dog.png. Name your audio file that goes with the dog image: dog.mp3. (.mp3 is an example). When the user selects the dog image, pass the name to a muatableString. Lets call the mutableString name selectedImage.
Right now, selectedImage should have a value of .png. (Or whatever extension you have.) Remove the last 3 letters of selectedImage like this:
func deleteCharactersInRange(_ aRange: NSRange)
Next you want to call the audio file using selectedImage, and add the extension name like this:
func appendString(_ aString: String)
So selectedImage's value should now be: dog.mp3. And you can now call the audio file with selectedImgae.
Hope this helps!!
Edit
Here is code to play audio files:
var player : AVAudioPlayer! = nil // will be Optional, must supply initializer
let path = NSBundle.mainBundle().pathForResource("audioFile", ofType:"m4a")
let fileURL = NSURL(fileURLWithPath: path)
player = AVAudioPlayer(contentsOfURL: fileURL, error: nil)
player.prepareToPlay()
player.delegate = self
player.play()

Resources