Showing posts with label Swift. Show all posts
Showing posts with label Swift. Show all posts

Thursday, April 14, 2022

Swift Arrays to Dictionaries with indices

The extension below is to facilitate the creation of dictionaries from arrays. In this case, the dictionary has the array element as the key and the index of that element as the value. 

Since I was only working with arrays that held unique values I added a guard statement to enforce that. If you remove it, then your the last duplicated element would have the index as its value.

extension Array where Element: Hashable {

    func toDictionary() -> [Element: Int] {

        guard Set(self).count == self.count else {

            fatalError("\(#function) requires arrays with unique values!")

        }

        return self

            .enumerated()

            .reduce(into: [Element: Int]()) { dict, tup in

                dict[tup.1] = tup.0

            }

    }


["hello", "world"].toDictionary() // ["world": 1, "hello": 0]


Saturday, June 01, 2019

100 Days of Swift

3. For a tougher challenge, take the image generation code out of cellForRowAt: generate all images when the app first launches, and use those smaller versions instead. For bonus points, combine the getDocumentsDirectory() method I introduced in project 10 so that you save the resulting cache to make sure it never happens again.

As a reminder, here’s the code for getDocumentsDirectory():
func getDocumentsDirectory() -> URL {
    let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
    return paths[0]
}

The above is from Day 98 of Paul Hudson's excellent course: 100 Days of Swift. It is Challenge #3 and there is even a "bonus" challenge inside the challenge! In approaching the solution--before coding--I wrote down my thoughts and then gathered snippets of code that I thought would help. My notes are below. I thought it might be helpful for others to share them without giving away the solution.

First, I jotted down the four main things I was concerned with:
  1. Read big images from bundle, see project 1.
  2. Render a image into a rect using CoreGraphics like in project 30. 
  3. Read the thumbnails in like project 10
  4. If a thumbnail does not exist then create it. Also like in project 10.
Next, I gathered the corresponding snippets of the code:

From project 1:
DispatchQueue.global(qos: .userInitiated).async { [weak self] in
    let fm = FileManager.default
    let path = Bundle.main.resourcePath!
    let items = try! fm.contentsOfDirectory(atPath: path)
    
    let pictureNames = items
        .filter { $0.hasPrefix("nssl") }
        .sorted { $0 < $1 }
    
    self?.storms = pictureNames.map {
        Storm(name: $0, imageName: $0) }
    
    DispatchQueue.main.async { [weak self] in
        self?.collectionView.reloadData()
    }
}

From project 30:
        let path = Bundle.main.path(forResource: imageRootName, ofType: nil)!
        let original = UIImage(contentsOfFile: path)!

        let renderRect = CGRect(origin: .zero, size: CGSize(width: 90, height: 90))
        let renderer = UIGraphicsImageRenderer(size: renderRect.size)
        
        let rounded = renderer.image { ctx in
            ctx.cgContext.addEllipse(in: renderRect)
            ctx.cgContext.clip()
            
            original.draw(in: renderRect)
        }

From project 10:

Write:
        let imageName = UUID().uuidString
        let imagePath = getDocumentsDirectory().appendingPathComponent(imageName)
        if let jpegData = image.jpegData(compressionQuality: 0.8) {
            try? jpegData.write(to: imagePath)
        }

Read:
        let path = getDocumentsDirectory().appendingPathComponent(person.imageName)
        cell.imageView.image = UIImage(contentsOfFile: path.path)