So far I have created a folder of images and I am able to assign 1 of the images to a UIImageView.
But what I want to do now is create a random generator, that will pick a random image from the folder, so if I was to create a button, I could display all of the images separately and randomly on a single UIImageView.
However, this folder is going to have more than 100 images, so I don't want to hard code each one into an array. Also, the names of the image has to be unique to the image itself.
I have been searching online but cannot find information on how to code what will suit my needs. So how would I get and display a random image(s) from a folder in swift?
You can name your images like this
image_0
image_1
image_2
Then use this code to populate your UIImageView
let numberOfImages: UInt32 = 100
let random = arc4random_uniform(numberOfImages)
let imageName = "image_\(random)"
imageView.image = UIImage(named: imageName)
Update
Since you don't want to rename your images you can create a plist file (type Array) where you put all the names of your images
And finally
func loadRandomImage() {
let path = NSBundle.mainBundle().pathForResource("Images", ofType: "plist")!
let names = NSArray(contentsOfFile: path) as! [String]
let random = Int(arc4random_uniform(UInt32(names.count)))
let imageName = names[random]
imageView.image = UIImage(named: imageName)
}
You either need to create an array of string filenames and pick a random filename from the array, or you need to use the file manager (NSFileManager) to get a list of the files in your folder and then pick from THAT array. Nether is very difficult.
Related
This is inside my viewForHeaderInSection. That means, this happens through each section.
for i in 0..<mySections[section].items!.count {
print("Valid For \(mySections[section].items[i]).")
let imagesArray = [header.icon1, header.icon2, header.icon3, header.icon4, header.icon5]
imagesArray[i].image = UIImage(named: "IconHamburger")
}
So for each section, I get the values for "Valid For".
E.g. Section 1 gets
Valid For ABC.
Valid For PQR.
Valid For XYZ.
Section 2 gets
Valid For ABC.
Valid For XYZ.
and so on...
My question is how do I assign image name to the images in my imagesArray? With condition like -
if Valid For is ABC, image name is "ImageAbc"
if Valid For is PQR, image name is "ImagePqr"
With my current code snippet above, all my image outlets get "IconHamburger" assigned.
Also, I have 5 images in my array and, the "Valid For" items are always <= 5.
So if I get 3 "Valid For" items, images need to be assigned only for the first three images.
Current output Screenshot from a section here -
It doesn't seem like you're very far off from what you're describing. Maybe this?
for i in 0..<mySections[section].items!.count {
let validItems = mySections[section].items[i]
let imagesArray = [header.icon1, header.icon2, header.icon3, header.icon4, header.icon5]
// Map your items to your image name formats (ABC -> ImageAbc)
let validImageNames = validItems.map { "Image" + $0.lowercased().capitalized }
// Update images in your image array
validImageNames.enumerated().forEach { index, imageName in
// Check for index in range
guard index < imagesArray.count else { return }
// Update image
imagesArray[index].image = UIImage(named: imageName)
}
}
In my app I have an array that looks like this:
var imgArray = [(Data, String)]()
It holds images and the images names and I append data by doing this:
if let firstImage = self.firstImage {
if let firstImageData = firstImage.compressImage() {
self.imgArray.append(firstImageData, self.randomImageName(length: 15))
}
}
Now I need to send all the image names inside that array using alamofire and I tried this:
for imgName in self.imgArray {
parameters["images[]"] = imgName.1
}
But my server responds by saying that images[] is empty, so I think that my ios code never sends an array named images[] containing the image names
Update
I changed the parameter to this:
parameters["images"] = [imgName.1]
This will upload one image, it seems like it overwrites the value each time so I need a way to grap all Strings from the imgArray array
Solution:
parameters["images"] = imgArray.map{$0.1}
This will add all of the image names from imgArray
My app is a slideshow that changes once a minute with a photo corresponding to each minute in the day. I currently have it checking the time and updating the image every tenth of second, as this will be on many devices at a large public event.
The relevant bits are:
#IBOutlet weak var theBrokenWatch: UIImageView!
if theBrokenWatch.image != UIImage(named: theImageName as String) {
theBrokenWatch.image = getUncachedImage(named: theImageName)
print("changed image to", theCurrentTime as String)
}
func getUncachedImage (named name : String) -> UIImage? {
if let imgPath = NSBundle.mainBundle().pathForResource(name, ofType: nil) {
return UIImage(contentsOfFile: imgPath)
}
return nil
}
Right now the if statement doesn't work. It did work when I was setting the image using imageNamed:, but that had major memory issues with 720 photos. (The CurrentTime is calculated and the matching image path built as theImageName.)
How can I check to see if the image needs to be changed (i.e. it's not what I just calculated as the current time)?
You don't want to use an uncached image to check for equality. Each time its generated, the image object will be different (the image data will be the same, but the wrapper object will be re-generated, and therefore not equal; image equality is not based of of actual bit contents).
Instead, key off the image name. Create a new var, imageName, and set that when you set the image. Then, when your timer fires, check your cached imageName against the new one, and only change the .image var if they're different.
Is it possible to count pictures with particular prefix in asset catalog ?
For exampe, I have images like:
Cocktail_01
Cocktail_02
...
Cocktail_nn
and other similar groups.
When my app starts, I do code like below:
var rec_cocktail = [UIImage]()
for i in 1..<32 {
if i < 10 {
let name: String = "Cocktail__0" + i.description
rec_cocktail.append(UIImage(named: name)!)
} else {
let name: String = "Cocktail__" + i.description
rec_cocktail.append(UIImage(named: name)!)
}
}
alcoholImages.append(rec_cocktail)
It's works perfect, but I have few groups to load and each one has different number of images. I have to check and change range each time when I add or remove picture from asset catalog.
It might be easier to use folders instead of Images.xcassets. Create a hierarchy you like on your computer and drag this into your Xcode project. Make sure you select:
Create folder references for any added folders
Then because you now have folder references when building your app you can iterate over items inside those folders using a loop.
For example I dragged in a folder called "Cocktail" and created the reference. Now i can iterate over the items inside this folder using:
let resourcePath = NSURL(string: NSBundle.mainBundle().resourcePath!)?.URLByAppendingPathComponent("Cocktail")
let resourcesContent = try! NSFileManager().contentsOfDirectoryAtURL(resourcePath!, includingPropertiesForKeys: nil, options: NSDirectoryEnumerationOptions.SkipsHiddenFiles)
for url in resourcesContent {
print(url)
print(url.lastPathComponent)
print(url.pathExtension!) // Optional
}
The url.lastPathComponent is the filename of the image (e.g. Cocktail_01.jpeg) and the url itself is the complete path of the image.
If you maintain a structure of folders it is very easy to iterate over them, if you want all the images in the same folder than you can create an array with just the image names you need and iterate over that using:
// The Array of Image names
var cocktailImagesArray : [String] = []
// Add images to the array in the 'for url in resourceContent' loop
if (url.lastPathComponent?.containsString("Cocktail")) {
self.cocktailImagesArray.append(url.lastPathComponent)
}
This way you have all the images which contain Cocktail and have added them to your array. Now you can simple iterate over your freshly created array using:
for imageName in self.cocktailImagesArray {
// Do something
}
I'm trying save some images to an array, and their name to another array as string with below code;
self.countryNamesArray.append(object["CountryName"] as! String)
let image = UIImage(data:imageData!)
self.countryImages.append(image!)
But it doesn't retrieve images with same order I saved while retrieve CountryNamesArray with correct order.
rowString = countryNamesArray[row]
myImageView.image = self.countryImages[row]
Should I use custom class to save images with string or are there any way to fix?