Merge pull request #55 from YusukeHosonuma/improve/render-performance
improve: use cache for thumbnail image
This commit is contained in:
@@ -43,6 +43,9 @@
|
||||
E5438E4524E2ACD4007A3EB7 /* BoardThumbnailImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5E6EB1524DFF33E0012E911 /* BoardThumbnailImage.swift */; };
|
||||
E5438E4724E2AD1D007A3EB7 /* BoardPreset.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5FA934B24C07A5500229AAA /* BoardPreset.swift */; };
|
||||
E5438E4924E2ADE3007A3EB7 /* LifeGame in Frameworks */ = {isa = PBXBuildFile; productRef = E5438E4824E2ADE3007A3EB7 /* LifeGame */; };
|
||||
E547C30A24E3F4CF0022DF3A /* MemoryStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = E547C30924E3F4CF0022DF3A /* MemoryStorage.swift */; };
|
||||
E547C30B24E3F4CF0022DF3A /* MemoryStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = E547C30924E3F4CF0022DF3A /* MemoryStorage.swift */; };
|
||||
E547C30C24E3F7710022DF3A /* MemoryStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = E547C30924E3F4CF0022DF3A /* MemoryStorage.swift */; };
|
||||
E54904AD24DD5DF0003AE7C7 /* MainGameViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5BA30B724BF05BC002D0564 /* MainGameViewModel.swift */; };
|
||||
E54904AF24DD5E2D003AE7C7 /* BoardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E54904AE24DD5E2D003AE7C7 /* BoardView.swift */; };
|
||||
E54904B024DD5E2D003AE7C7 /* BoardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E54904AE24DD5E2D003AE7C7 /* BoardView.swift */; };
|
||||
@@ -170,6 +173,7 @@
|
||||
E5438E3924E2AB0B007A3EB7 /* LifeGameWidget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LifeGameWidget.swift; sourceTree = "<group>"; };
|
||||
E5438E3B24E2AB0D007A3EB7 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
E5438E3D24E2AB0D007A3EB7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
E547C30924E3F4CF0022DF3A /* MemoryStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemoryStorage.swift; sourceTree = "<group>"; };
|
||||
E54904AE24DD5E2D003AE7C7 /* BoardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BoardView.swift; sourceTree = "<group>"; };
|
||||
E54B7AF024DB0043005E1B55 /* HeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeaderView.swift; sourceTree = "<group>"; };
|
||||
E558A97224DB70D00012E443 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
|
||||
@@ -322,6 +326,14 @@
|
||||
path = Shared;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E547C30824E3F4AA0022DF3A /* Cache */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E547C30924E3F4CF0022DF3A /* MemoryStorage.swift */,
|
||||
);
|
||||
path = Cache;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E54904AB24DD5D6F003AE7C7 /* BoardSelect */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -588,6 +600,7 @@
|
||||
E5FA934A24C07A3D00229AAA /* Model */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E547C30824E3F4AA0022DF3A /* Cache */,
|
||||
E52FE5DB24DC00E100D93764 /* Firestore */,
|
||||
E5FA934B24C07A5500229AAA /* BoardPreset.swift */,
|
||||
E5CE237224C199F200BC5820 /* LifeGameContext.swift */,
|
||||
@@ -931,6 +944,7 @@
|
||||
E5438E3A24E2AB0B007A3EB7 /* LifeGameWidget.swift in Sources */,
|
||||
E518C89824E3690600B02027 /* Color+.swift in Sources */,
|
||||
E56A422824E2BB6800F9AC24 /* BoardDocument.swift in Sources */,
|
||||
E547C30C24E3F7710022DF3A /* MemoryStorage.swift in Sources */,
|
||||
E518C89624E368A700B02027 /* UserDefaultGroup.swift in Sources */,
|
||||
E5438E4724E2AD1D007A3EB7 /* BoardPreset.swift in Sources */,
|
||||
E5438E4524E2ACD4007A3EB7 /* BoardThumbnailImage.swift in Sources */,
|
||||
@@ -967,6 +981,7 @@
|
||||
E507EBEE24CC1106002A6EC4 /* SettingView.swift in Sources */,
|
||||
E54B7AF124DB0043005E1B55 /* HeaderView.swift in Sources */,
|
||||
E5BA30B824BF05BC002D0564 /* MainGameViewModel.swift in Sources */,
|
||||
E547C30A24E3F4CF0022DF3A /* MemoryStorage.swift in Sources */,
|
||||
E5D9F27324BEBDBD009A526B /* Application.swift in Sources */,
|
||||
E5B0572824CC3465005EE1AA /* CellView.swift in Sources */,
|
||||
E5FA935024C07AE300229AAA /* Collection+.swift in Sources */,
|
||||
@@ -1013,6 +1028,7 @@
|
||||
E571536A24D51B9F003B4C9E /* UserDefault.swift in Sources */,
|
||||
E5CE237424C199F200BC5820 /* LifeGameContext.swift in Sources */,
|
||||
E55F7AA824DD0D9300DBC175 /* ContentView.swift in Sources */,
|
||||
E547C30B24E3F4CF0022DF3A /* MemoryStorage.swift in Sources */,
|
||||
E5604AA124CC3ED600EA59C3 /* PreferenceView.swift in Sources */,
|
||||
E573BD8224D053F90096BF75 /* LifeGameCommands.swift in Sources */,
|
||||
E518C89424E3684A00B02027 /* UserDefaultSettingGroup.swift in Sources */,
|
||||
|
||||
@@ -41,7 +41,9 @@ struct Provider: TimelineProvider {
|
||||
|
||||
// とりあえずランダムでチョイスするだけ
|
||||
let document = documents.randomElement()!
|
||||
let data = LifeGameData(title: document.title, board: document.makeBoard().extended(by: .die), url: URL(string: "board:///\(document.id!)")!)
|
||||
let data = LifeGameData(title: document.title,
|
||||
board: document.makeBoard().extended(by: .die),
|
||||
url: URL(string: "board:///\(document.id!)")!, cacheKey: document.id!)
|
||||
let entry = LifeGameEntry(date: entryDate, relevance: data)
|
||||
entries.append(entry)
|
||||
}
|
||||
@@ -61,6 +63,7 @@ struct LifeGameData {
|
||||
var title: String
|
||||
var board: Board<Cell>
|
||||
var url: URL = URL(string: "board:///0")!
|
||||
var cacheKey: String?
|
||||
}
|
||||
|
||||
struct LifeGameWidgetEntryView : View {
|
||||
@@ -71,7 +74,7 @@ struct LifeGameWidgetEntryView : View {
|
||||
var body: some View {
|
||||
HStack {
|
||||
VStack(alignment: .leading) {
|
||||
BoardThumbnailImage(board: entry.relevance.board, cellColor: cellColor)
|
||||
BoardThumbnailImage(board: entry.relevance.board, cellColor: cellColor, cacheKey: entry.relevance.cacheKey)
|
||||
Text(entry.relevance.title)
|
||||
.font(.system(.footnote, design: .monospaced))
|
||||
.foregroundColor(.gray)
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
//
|
||||
// MemoryStorage.swift
|
||||
// LifeGameApp
|
||||
//
|
||||
// Created by Yusuke Hosonuma on 2020/08/12.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
final class ThumbnailImageCacheStorage {
|
||||
static var shared = ThumbnailImageCacheStorage()
|
||||
|
||||
private let cache = NSCache<NSString, UIImage>()
|
||||
|
||||
func store(key: String, image: UIImage) {
|
||||
cache.setObject(image, forKey: key as NSString)
|
||||
}
|
||||
|
||||
func value(forKey key: String) -> UIImage? {
|
||||
guard let value = cache.object(forKey: key as NSString) else { return nil }
|
||||
return value
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,7 @@ struct BoardSelectCell: View {
|
||||
switch style {
|
||||
case .grid:
|
||||
VStack {
|
||||
BoardThumbnailImage(board: item.makeBoard().extended(by: .die))
|
||||
BoardThumbnailImage(board: item.makeBoard().extended(by: .die), cacheKey: item.id)
|
||||
.matchedGeometryEffect(id: "thumbnail-\(item.title)", in: nspace)
|
||||
|
||||
HStack {
|
||||
@@ -54,7 +54,7 @@ struct BoardSelectCell: View {
|
||||
.foregroundColor(.yellow)
|
||||
}
|
||||
Spacer()
|
||||
BoardThumbnailImage(board: item.makeBoard().extended(by: .die))
|
||||
BoardThumbnailImage(board: item.makeBoard().extended(by: .die), cacheKey: item.id)
|
||||
.frame(width: 60, height: 60, alignment: .center)
|
||||
.matchedGeometryEffect(id: "thumbnail-\(item.title)", in: nspace)
|
||||
}.padding()
|
||||
|
||||
@@ -13,6 +13,9 @@ struct BoardThumbnailImage: View {
|
||||
|
||||
var board: Board<Cell>
|
||||
var cellColor: Color?
|
||||
var cacheKey: String?
|
||||
|
||||
private let cacheStorage = ThumbnailImageCacheStorage.shared
|
||||
|
||||
var body: some View {
|
||||
Image(uiImage: thumbnailImage)
|
||||
@@ -38,7 +41,21 @@ struct BoardThumbnailImage: View {
|
||||
}
|
||||
|
||||
private var thumbnailImage: UIImage {
|
||||
let scale = max(2, 200 / board.size)
|
||||
guard let key = cacheKey else {
|
||||
return renderImage()
|
||||
}
|
||||
|
||||
if let image = cacheStorage.value(forKey: key) {
|
||||
return image
|
||||
} else {
|
||||
let image = renderImage()
|
||||
cacheStorage.store(key: key, image: image)
|
||||
return image
|
||||
}
|
||||
}
|
||||
|
||||
private func renderImage() -> UIImage {
|
||||
let scale = max(2, 140 / board.size)
|
||||
let size = CGSize(width: board.size * scale + 1, height: board.size * scale + 1)
|
||||
|
||||
return UIGraphicsImageRenderer(size: size)
|
||||
@@ -70,7 +87,7 @@ struct BoardThumnailImage_Previews: PreviewProvider {
|
||||
view(preset: .nebura, colorScheme: .light)
|
||||
view(preset: .spaceShip, colorScheme: .dark)
|
||||
}
|
||||
|
||||
|
||||
static func view(preset: BoardPreset, colorScheme: ColorScheme) -> some View {
|
||||
BoardThumbnailImage(board: preset.board.board)
|
||||
.previewLayout(.fixed(width: 200.0, height: 200.0))
|
||||
|
||||
Reference in New Issue
Block a user