0

I try to do customized tableviewCell with imageView in my chat app.
And I need to do 3x3 grid images in each cell.
I face a problem that the imageView memory problem.
How to solve the cell contain 9 imageviews in each cell to prevent memory increase.
Or any good idea to solve it.
I need to decrease memory.
Thanks.

This is my code:

case .group:
        var drawSequence:[Int] = [Int]()
        var drawIcons:[String] = [String]()

        let string:String = chatroom.users
        let tempArr = string.components(separatedBy: ",")
        var stringArr = Array<String>()

        for a in tempArr {

            var b = a.replacingOccurrences(of: "\"", with: "")
            b = b.replacingOccurrences(of: "[", with: "")
            b = b.replacingOccurrences(of: "]", with: "")
            stringArr.append(b)
        }

        stringArr.forEach({ (id) in
            drawIcons.append(id)
        })

        let g:CGFloat = 1
        var x:CGFloat = g
        var y:CGFloat = g
        var w:CGFloat = (defaultBigIconWidth - g)/3 - g
        switch drawIcons.count {
        case let count where count >= 9:
            drawSequence = [3,3,3]
            break
        case 8:
            drawSequence = [2,3,3]
            break
        case 7:
            drawSequence = [1,3,3]
            break
        case 6:
            drawSequence = [3,3]
            y = defaultBigIconWidth/2-w
            break
        case 5:
            drawSequence = [2,3]
            y = defaultBigIconWidth/2-w
            break
        case 4:
            w = (defaultBigIconWidth - g)/2 - g
            drawSequence = [2,2]
            y = defaultBigIconWidth/2-w
            break
        case 3:
            w = (defaultBigIconWidth - g)/2 - g
            drawSequence = [1,2]
            y = defaultBigIconWidth/2-w
            break
        case 2:
            w = (defaultBigIconWidth - g)/2 - g
            drawSequence = [2]
            y = (defaultBigIconWidth-w)/2
            break
        default:
            break
        }

        for row in drawSequence {
            switch row {
            case 1:
                x = (defaultBigIconWidth-w)/2
                break
            case 2:
                x = defaultBigIconWidth/2-w
                break
            default:
                x = g
                break
            }
            for _ in 0..<row {
                let id = drawIcons.removeFirst()
                let ui:UIImageView = GeneratorAvatarImageView()
                ui.frame = CGRect(x: x, y: y, width: w, height: w)
                icon.addSubview(ui)

                if id == currentUser.id {
                    user = contacts[currentUser.id]
                    ImageFromUrl(imageView: ui, url: (user?.avatar)!, type: "user")
                }else{
                    user = contacts[id]
                    ImageFromUrl(imageView: ui, url: (user?.avatar)!, type: "user")
                }
                x += w+g
            }
            y += w+g
        }
        break


func ImageFromUrl(imageView:UIImageView,url:String,type:String) {

if url.isEmpty {
    imageView.image = #imageLiteral(resourceName: "defaultIcon")
    print("Url is empty.")
    return
}

var documentsDirectoryURL:URL

if type == "user" {

    documentsDirectoryURL = try! FileManager().url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true).appendingPathComponent("Image/User/")

    let exist = FileManager.default.fileExists(atPath: documentsDirectoryURL.path)

    if !exist {

        do {
            try FileManager.default.createDirectory(atPath: documentsDirectoryURL.path, withIntermediateDirectories: true, attributes: nil)
        } catch let error as NSError {
            debug(object: error)
        }
    }

}

// create a name for your image
let fileName = url.md5()
let fileURL = documentsDirectoryURL.appendingPathComponent(fileName)
let urlString = URL(string: url)

if let image = UIImage(contentsOfFile: fileURL.path) {
    imageView.image = image
    return
}

DispatchQueue.global().async {
    let data = try? Data(contentsOf: urlString!) //make sure your image in this url does exist, otherwise unwrap in a if let check / try-catch
    if data != nil
    {
        if let image = UIImage(data: data!)
        {
            if !FileManager.default.fileExists(atPath: fileURL.path) {

                var c = [UInt32](repeating: 0, count: 1)
                (data! as NSData).getBytes(&c, length: 1)
                switch (c[0]) {
                case 0xFF:
                    print("Download jpg: \(url)")
                    if let jpegData = UIImageJPEGRepresentation(image, 0.5) {

                        do {
                            try jpegData.write(to: fileURL, options: .atomic)
                        } catch {
                            debug(object: error)
                        }
                    }
                case 0x89:
                    print("Download png: \(url)")
                    if let pngData = UIImagePNGRepresentation(image) {
                        do {
                            try pngData.write(to: fileURL, options: .atomic)
                        } catch {
                            debug(object: error)
                        }
                    }
                case 0x47:
                    print("Download gif: \(url)")
                default:
                    print("Download unknown: \(c[0])\(url)")
                }

            } else {
                //                    debug(object:"file already exists")
            }

            DispatchQueue.main.async {
                imageView.image = image
            }
        }
    }
}
}

func GeneratorAvatarImageView() -> UIImageView {

let imageview = UIImageView()
imageview.layer.masksToBounds = true
imageview.layer.cornerRadius = 2
imageview.backgroundColor = UIColor.clear
imageview.contentMode = UIViewContentMode.scaleAspectFill
return imageview
}

IMAGE HERE

tolerate_Me_Thx
  • 387
  • 2
  • 7
  • 21

1 Answers1

0

My solution is add a UICollectionView to your cell, it will be better than add 9 ImageViews to your cell. and I've tried this method, it will not cause memory problems.

Explanation: I think the images on UICollectionView that you added to your cell can be reused, although it add more views on your cell but it has cell reused function. so it will not cause memory problems.

Hope that it can solve your problem.

Versus
  • 404
  • 4
  • 13
  • Add collectionView why be better than imageViews. – tolerate_Me_Thx Oct 31 '17 at 02:47
  • Actually, it won't be better for sure. – trungduc Oct 31 '17 at 02:48
  • oh. it's so complex to me. Have any explain? – tolerate_Me_Thx Oct 31 '17 at 02:51
  • It can't be better. Adding `collectionView` means that you will add more views to you cell, more logic to your cell. Memory will increase instead of decreasing. – trungduc Oct 31 '17 at 02:56
  • 1
    I've update my answer, I think ImageViews on UICollectionView's cell can be reused, so it will not cause memory problems. – Versus Oct 31 '17 at 03:05
  • For me. I've tried this way on my own project. and it does work for me. – Versus Oct 31 '17 at 03:06
  • ImageViews on UITableViewCell can be reused too, so i think it's hard to resolve problem with UICollectionViewCell inside UITableViewCell – trungduc Oct 31 '17 at 03:08
  • But the difference is: every image is a cell in UICollectionView, another is 9 images on a UITableView is a cell. so that's difference. – Versus Oct 31 '17 at 03:17
  • By the way. I think the solution i offered is not the main problem of his code, maybe images cache is the point – Versus Oct 31 '17 at 03:19
  • Agree. I think loops for loading image can be the reason for his issue. – trungduc Oct 31 '17 at 03:20
  • @tolerate_Me_Thx this will work fine and even your code work will be optimized. Your screen will be dynamic as per the number of images. Cell will be automatically manage your memory as if collectioncell is disappeared from the screen then its memory will be released. It can be complex but its not too hard such that you can not achieve this. **Take ref->** https://medium.com/@adinugroho/fixed-height-uicollectionview-inside-uitableview-79f24657d08f – dahiya_boy Oct 31 '17 at 04:24