ScrollView that deletes image in based on location - ios

I have made a scrollview, and made an array of images (which I will later add an option for the user to post images into that array and friends images will fill into that array) and want to have the user be able to see a photo and it tracks it.
I have created a for loop that added photos into the array, but when I created an if statement to take out an item in the array, I got an error because I would remove the image[i] from the array and I kinda know why this is happening, but want to fix it. So basically I need to take out an image in the array. Please help me out I'm still learning.
class ViewController: UIViewController {
var imageArray = [UIImage]()
#IBOutlet weak var mainScrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
mainScrollView.frame = view.frame
imageArray = [#imageLiteral(resourceName: "dubai6"), #imageLiteral(resourceName: "dubai2"), #imageLiteral(resourceName: "dubai7"), #imageLiteral(resourceName: "dubai4"), #imageLiteral(resourceName: "dubai3"), #imageLiteral(resourceName: "dubai5"), #imageLiteral(resourceName: "DigitalDrawingPreview"), #imageLiteral(resourceName: "denarus"), #imageLiteral(resourceName: "dubai1")]
for i in 0..<imageArray.count {
let imageView = UIImageView()
imageView.contentMode = .scaleAspectFit
imageView.image = imageArray[i]
let xPosition = self.view.frame.width * CGFloat(i)
imageView.frame = CGRect(x: xPosition, y: 0, width: self.view.frame.width, height: self.mainScrollView.frame.height)
mainScrollView.contentSize.width = mainScrollView.frame.width * CGFloat(i + 1)
mainScrollView.addSubview(imageView)
}
for i in 0..<imageArray.count {
if (i >= 2) {
imageArray.remove(at: (i - 2))
}
}
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Thank you fellow better programmers.

You can't remove an element from a array while traversing it so you had to use a temp array
class ViewController: UIViewController {
var imageArray = [UIImage]()
#IBOutlet weak var mainScrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
mainScrollView.frame = view.frame
imageArray = [#imageLiteral(resourceName: "dubai6"), #imageLiteral(resourceName: "dubai2"), #imageLiteral(resourceName: "dubai7"), #imageLiteral(resourceName: "dubai4"), #imageLiteral(resourceName: "dubai3"), #imageLiteral(resourceName: "dubai5"), #imageLiteral(resourceName: "DigitalDrawingPreview"), #imageLiteral(resourceName: "denarus"), #imageLiteral(resourceName: "dubai1")]
for i in 0..<imageArray.count {
let imageView = UIImageView()
imageView.contentMode = .scaleAspectFit
imageView.image = imageArray[i]
let xPosition = self.view.frame.width * CGFloat(i)
imageView.frame = CGRect(x: xPosition, y: 0, width: self.view.frame.width, height: self.mainScrollView.frame.height)
mainScrollView.contentSize.width = mainScrollView.frame.width * CGFloat(i + 1)
mainScrollView.addSubview(imageView)
}
let tempArr = imageArray
for i in 0..<tempArr.count {
if (i >= 2) { // Breakpoint here
imageArray.remove(at: (i - 2))
}
}
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
use step over to go through each line of for loop until it crashes and then print the value of i at that time by hovering cursor over it or type command at console po i and enter

Related

how to make save button to swift 5?

I'm creating a wallpaper app for iOS. I've created a UIImageView, but am stuck on saving the image. I have solved the permissions but am unable to have the user save the image. I created the save button itself, but I don't know to make save any image from the image array in the user's image gallery.
Here is my code so far:
class ViewController: UIViewController {
#IBOutlet var imageview: [UIScrollView]!
#IBOutlet weak var saveButton: UIButton!
#IBAction func saveButtonPressed(_ sender: UIButton) {
// TODO: - How to save the image here
}
let scrollView: UIScrollView = {
let scroll = UIScrollView()
scroll.isPagingEnabled = true
scroll.showsVerticalScrollIndicator = false
scroll.showsHorizontalScrollIndicator = false
scroll.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
return scroll
}()
var imageArray = [UIImage]()
func setupImages(_ images: [UIImage]){
for i in 0..<images.count {
let imageView = UIImageView()
imageView.image = images[i]
let xPosition = UIScreen.main.bounds.width * CGFloat(i)
imageView.frame = CGRect(x: xPosition, y: 0, width: scrollView.frame.width, height: scrollView.frame.height)
imageView.contentMode = .scaleAspectFit
scrollView.contentSize.width = scrollView.frame.width * CGFloat(i + 1)
scrollView.addSubview(imageView)
//scrollView.delegate = (self as! UIScrollViewDelegate)
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
view.addSubview(scrollView)
imageArray = [#imageLiteral(resourceName: "1"),#imageLiteral(resourceName: "10"),#imageLiteral(resourceName: "9"),#imageLiteral(resourceName: "8"),#imageLiteral(resourceName: "3")]
setupImages(imageArray)
}
}
You will need to add a saveImage function:
func saveImage(image: UIImage) -> Bool {
guard let data = UIImageJPEGRepresentation(image, 1) ?? UIImagePNGRepresentation(image) else {
return false
}
guard let directory = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false) as NSURL else {
return false
}
do {
try data.write(to: directory.appendingPathComponent("fileName.png")!)
return true
} catch {
print(error.localizedDescription)
return false
}
}
And then in saveButtonPressed:
let success = saveImage(image: imageArray[0])
print("Did \(success ? "" : "not ")store image successfully")
You'll need to add some logic to actually select the image.

UIView.animate with imageArray inside of UIScrollView but with effect like paging enable

I'm new in Swift but I have some basic experience.
I have successfully created an animation with three images and they repeat themselves. But I would like the effect of this repetition to be like when you in attributes inspector of UIScrollView check paging enable.
Inside of options: UIView.AnimationOptions I tried different Constants but I can not find that suits me.
My question: Can I animate image array like you swipe images in scroll view with paging enable?
class ViewController: UIViewController {
#IBOutlet weak var mainScrollView: UIScrollView!
var imageArray = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
imageArray = [UIImage(named: "forest")!, UIImage(named: "slika1")!, UIImage(named: "slika2")!]
for i in 0..<imageArray.count {
let imageView = UIImageView()
imageView.image = imageArray[i]
imageView.contentMode = .scaleAspectFit
let xPosition = self.miniView.frame.width * CGFloat(i)
imageView.frame = CGRect(x: xPosition, y: 0, width: self.mainScrollView.frame.width, height: self.mainScrollView.frame.height)
mainScrollView.contentSize.width = mainScrollView.frame.width * CGFloat(i + 1)
mainScrollView.addSubview(imageView)
}
startAnimating()
}
func startAnimating() {
var newOffset = mainScrollView.contentOffset
newOffset.x = 0.0
newOffset.x += mainScrollView.frame.width * CGFloat(imageArray.count - 1)
UIView.animate(withDuration: Double(imageArray.count), delay: 5, options: [.repeat, .allowUserInteraction], animations: {
self.mainScrollView.contentOffset = newOffset
})
}
}
Ok, if i correctly understand what you want, this is the correct answer.
Animate page by page, with a 5 seconds delay with one animation and another.
You need to use Timer.scheduledTimer to trigger method that scroll to the next page. With that solution, you can check paging enable ON, so the user can change the page itself.
I hope it helps
class ViewController: UIViewController {
#IBOutlet weak var mainScrollView: UIScrollView!
var imageArray = [UIImage]()
var currentPage = 0
override func viewDidLoad() {
super.viewDidLoad()
imageArray = [UIImage(named: "forest")!, UIImage(named: "slika1")!, UIImage(named: "slika2")!]
for i in 0..<imageArray.count {
let imageView = UIImageView()
imageView.image = imageArray[i]
imageView.contentMode = .scaleAspectFit
let xPosition = self.miniView.frame.width * CGFloat(i)
imageView.frame = CGRect(x: xPosition, y: 0, width: self.mainScrollView.frame.width, height: self.mainScrollView.frame.height)
mainScrollView.contentSize.width = mainScrollView.frame.width * CGFloat(i + 1)
mainScrollView.addSubview(imageView)
}
Timer.scheduledTimer(timeInterval: 5, target: self, selector: #selector(startAnimating), userInfo: nil, repeats: true)
}
#objc func startAnimating() {
//that line check if the current page is the last one, and set it to the first, otherwise, it increment the currentPage
self.currentPage = (self.currentPage == imageArray.count-1) ? 0 : self.currentPage+1
var newOffset = mainScrollView.contentOffset
newOffset.x = mainScrollView.frame.width * CGFloat(self.currentPage)
self.mainScrollView.setContentOffset(newOffset, animated: true)
}
}

Change label text while image in UIScrollview changes

I want to create an image gallery similar to this:
http://sweettutos.com/2015/04/13/how-to-make-a-horizontal-paging-uiscrollview-with-auto-layout-in-storyboards-swift/
Where each time the user swipes and the image changes and the label title changes.I have written the code and included the if statement, however, it does not work properly and it only changes as one value.
Here is my code:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var mainscrollview: UIScrollView!
var imageArray = [UIImage]()
#IBOutlet var label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
mainscrollview.frame = view.frame
imageArray = [#imageLiteral(resourceName: "goku"), #imageLiteral(resourceName: "boruto"), #imageLiteral(resourceName: "tail"), #imageLiteral(resourceName: "sage"),#imageLiteral(resourceName: "tobi")]
for i in 0..<imageArray.count{
let imageView = UIImageView()
imageView.image = imageArray[i]
imageView.contentMode = .scaleAspectFit
let xPosition = self.view.frame.width * CGFloat(i)
imageView.frame = CGRect(x: xPosition, y: 0, width: self.mainscrollview.frame.width,height: self.mainscrollview.frame.height)
mainscrollview.contentSize.width = mainscrollview.frame.width * CGFloat(i + 1)
mainscrollview.addSubview(imageView)
let gokuImage = UIImage(named: "goku")
let borutoImage = UIImage(named: "boruto")
if imageView.image == gokuImage{
label.text = "Goku"
}
if imageView.image == borutoImage{
label.text = "bor"
}
}
}
}
This is where the project is going wrong:
let gokuImage = UIImage(named: "Goku")
let borutoImage = UIImage(named: "boruto")
if imageView.image == gokuImage{
label.text = "Goku"
}
if imageView.image == borutoImage{
label.text = "bor"
}
I think this is because the if statement can not directly access the current image that is being displayed in the UIScroll view.
Here is the link to my project: http://www.mediafire.com/file/adkzcpvdtodlyl5/gallery_copy.zip
To achieve what you want to do, here is one of the option available which is fairly simple:
Your label is in your ScrollView, so it will scroll with your first image. You need to move it above your ScrollView, at the same hierarchy level as the ScrollView.
In order to change your label's text when you scroll, you can detect when your page has stopped decelerating. To do so:
(a) Add UIScrollViewDelegate to class ViewController: UIViewController,
(b) in viewDidLoad(), add 'mainscrollview.delegate = self',
(c) write the 'scrollViewDidEndDecelerating' method.
In the end, your code should look like this:
import UIKit
class ViewController: UIViewController, UIScrollViewDelegate {
#IBOutlet weak var mainscrollview: UIScrollView!
#IBOutlet var label: UILabel!
var imageArray = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
imageArray = [#imageLiteral(resourceName: "goku"), #imageLiteral(resourceName: "boruto"), #imageLiteral(resourceName: "tail"), #imageLiteral(resourceName: "sage"),#imageLiteral(resourceName: "tobi")]
mainscrollview.frame = view.frame
mainscrollview.delegate = self
label.text = "Initial label value is Boruto"
for i in 0..<imageArray.count{
let imageView = UIImageView()
imageView.image = imageArray[i]
imageView.contentMode = .scaleAspectFit
let xPosition = self.view.frame.width * CGFloat(i)
imageView.frame = CGRect(x: xPosition, y: 0, width: self.mainscrollview.frame.width,height: self.mainscrollview.frame.height)
mainscrollview.contentSize.width = mainscrollview.frame.width * CGFloat(i + 1)
mainscrollview.addSubview(imageView)
}
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView){
// Test the offset and calculate the current page after scrolling ends
let pageWidth:CGFloat = mainscrollview.frame.width
let currentPage:CGFloat = floor((mainscrollview.contentOffset.x-pageWidth/2)/pageWidth)+1
// Change the text accordingly
if Int(currentPage) == 0{
label.text = "Boruto"
}else if Int(currentPage) == 1{
label.text = "Goku"
}else if Int(currentPage) == 2{
label.text = "Sage"
}else if Int(currentPage) == 3{
label.text = "Tail"
}else if Int(currentPage) == 4{
label.text = "Tobi"
}else{
label.text = "Other character"
}
}
}
The first thing you should do is remove the label from the scroll view and add it into the main view i.e the scrollview and the label should have sibling relationship rather than parent-child relationship.
Modify your ViewController accordingly
class ViewController: UIViewController, UIScrollViewDelegate {
// your other code
override func viewDidLoad() {
super.viewDidLoad()
mainscrollview.delegate = self
// your other code
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let imageNumber = round(scrollView.contentOffset.x / scrollView.frame.size.width)
switch imageNumber {
case 0:
label.text = "Goku"
case 1:
label.text = "Bor"
case 2:
label.text = "Tail"
case 3:
label.text = "Sage"
case 4:
label.text = "Tobi"
default:
label.text = "Unknown"
}
}
}
You use the UILabel from storyboards and UIImageView from the code. You add all the images to the scrollView, so that everyone follows one another, but you use your label only with the first image.
In other words, you need to add UILabel to the code and add it to each image. Instead of a lot of "if-cycle", I suggest you use an array of labels, just as you use the image.
var labelArray = [String]()
// in viewDidLoad add your label names
labelArray = ["goku", "boruto", "next word", "next word", "next word"]
// create UILabel
let yourLabel = UILabel(frame: CGRect(x: xPosition, y: self.mainscrollview.frame.height - 100, width: self.mainscrollview.frame.width, height: 40))
// add each labelName to each image
yourLabel.text = labelArray[i]
// add image and label to scrollView
mainscrollview.addSubview(imageView)
mainscrollview.addSubview(yourLabel)

Delete image out of array at given index

I have created and initialized a scrollview that pulls from an array of images. So a user swipes past a photo, then another, and I need to delete the image based on the location of the current image I have created a for loop that deletes the image i-- in the array, but this crashes because I can't delete the i. Is there a way I can accomplish this? Thank you: here is my code
class ViewController: UIViewController {
var imageArray = [UIImage]()
#IBOutlet weak var mainScrollView: UIScrollView!
func scrollViewDidScroll(_ scrollView: UIScrollView) {
for i in 0..<imageArray.count {
if i >= 3 {
imageArray.remove(at: i - 2)
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
mainScrollView.frame = view.frame
imageArray = [#imageLiteral(resourceName: "dubai6"), #imageLiteral(resourceName: "dubai2"), #imageLiteral(resourceName: "dubai7"), #imageLiteral(resourceName: "dubai4"), #imageLiteral(resourceName: "dubai3"), #imageLiteral(resourceName: "dubai5"), #imageLiteral(resourceName: "DigitalDrawingPreview"), #imageLiteral(resourceName: "denarus"), #imageLiteral(resourceName: "dubai1")]
for i in 0..<imageArray.count {
let imageView = UIImageView()
imageView.contentMode = .scaleAspectFit
imageView.image = imageArray[i]
let xPosition = self.view.frame.width * CGFloat(i)
imageView.frame = CGRect(x: xPosition, y: 0, width: self.view.frame.width, height: self.mainScrollView.frame.height)
mainScrollView.contentSize.width = mainScrollView.frame.width * CGFloat(i + 1)
mainScrollView.addSubview(imageView)
}
Rather than using a UIScrollView, I would recommend using a UITableView or UICollectionView. It is very easy to manage the data model and then call table.reloadData().
You would track the scroll position with the ScrollViewDelegate method scrollViewDidScroll(_ scrollView) and force a reload once you've scrolled far enough.

".gif" File loads and then disappears after 1 second

I am a beginner to Swift, so I would probably need some explaining. Please bear with me. I am creating an app that needs to load a .gif file, but when I run it on the simulator it loads for one second (or even less) and then becomes blank, but the screen itself stays on the page that had the .gif file on it. I'm not sure why this happens. Can someone explain? Thank you!
Here is the code:
import UIKit
class ViewController: UIViewController {
#IBAction func Burning(sender: AnyObject) {
let imageData = NSData(contentsOfURL: NSBundle.mainBundle().URLForResource("fire", withExtension: "gif")!)
let imageGif = UIImage.gifWithData(imageData!)
let imageView = UIImageView(image: imageGif)
imageView.frame = CGRect(x: 0.0, y:0.0, width:414.0, height: 685.0)
view.addSubview(imageView)
}
#IBAction func Smashing(sender: AnyObject) {
let imageData = NSData(contentsOfURL: NSBundle.mainBundle().URLForResource("water", withExtension: "gif")!)
let imageGif = UIImage.gifWithData(imageData!)
let imageView = UIImageView(image: imageGif)
imageView.frame = CGRect(x: 0.0, y:0.0, width:414.0, height: 685.0)
view.addSubview(imageView)
}
#IBAction func Shredding(sender: AnyObject) {
let imageData = NSData(contentsOfURL: NSBundle.mainBundle().URLForResource("shredder", withExtension: "gif")!)
let imageGif = UIImage.gifWithData(imageData!)
let imageView = UIImageView(image: imageGif)
imageView.frame = CGRect(x: 0.0, y:0.0, width:414.0, height: 685.0)
view.addSubview(imageView)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

Resources