Slide 1

Slide 1 text

ͻΊ͠ʢ!IJNFTIJ@UFDIʣ "DUPSͰ$PSF%BUBΛ εϨου͔Βղ์͠Α͏ !J04%$+BQBO

Slide 2

Slide 2 text

$PSF%BUB࢖͍ͬͯ·͔͢ʁ 2

Slide 3

Slide 3 text

$PSF%BUB ҆શʹ࢖͍ͬͯ·͔͢ʁ 3

Slide 4

Slide 4 text

ຊ೔ͷΞδΣϯμ w 4XJGU$PODVSSFODZͷ΋ͱͰ$PSF%BUBΛΑΓ҆શʹ࢖͑ΔΑ͏ ʹ͢ΔͨΊͷख๏Λߟ͑Δɻ 4

Slide 5

Slide 5 text

ຊ೔ͷΞδΣϯμ w 4XJGU$PODVSSFODZͷ΋ͱͰ$PSF%BUBΛΑΓ҆શʹ࢖͑ΔΑ͏ ʹ͢ΔͨΊͷख๏Λߟ͑Δɻ w $PSF%BUBͷεϨουҧ൓ͱ͸ͳʹ͔ 5

Slide 6

Slide 6 text

ຊ೔ͷΞδΣϯμ w 4XJGU$PODVSSFODZͷ΋ͱͰ$PSF%BUBΛΑΓ҆શʹ࢖͑ΔΑ͏ ʹ͢ΔͨΊͷख๏Λߟ͑Δɻ w $PSF%BUBͷεϨουҧ൓ͱ͸ͳʹ͔ w εϨουҧ൓ΛίϯύΠϧ࣌ʹνΣοΫ͢Δख๏ 6

Slide 7

Slide 7 text

͜ͷτʔΫͷର৅ w $PSF%BUBͱ4XJGU$PODVSSFODZΛগ͠Ͱ΋৮ͬͨ͜ͱ͕͋Δਓ w ඇಉظॲཧ΍σʔλڝ߹ʹۤ͠Μͩ͜ͱ͕͋Δਓ 7

Slide 8

Slide 8 text

$PSF%BUBͷ εϨουҧ൓ͱ͸ͳʹ͔ʁ 8

Slide 9

Slide 9 text

͜ͷίʔυ͸҆શͳ࣮૷͔ʁ 9 class CoreDataController { private var entity: CoreDataEntity? = nil private let moc: NSManagedObjectContext init(container: NSPersistentContainer) { self.moc = container.newBackgroundContext() } func configure() throws { entity = CoreDataEntity(context: moc) try moc.save() } }

Slide 10

Slide 10 text

10 class CoreDataController { private var entity: CoreDataEntity? = nil private let moc: NSManagedObjectContext init(container: NSPersistentContainer) { self.moc = container.newBackgroundContext() } func configure() throws { entity = CoreDataEntity(context: moc) try moc.save() } } .BOBHFEPCKFDUDPOUFYUΛൃߦ .BOBHFEPCKFDUΛੜ੒ɺอଘ ͜ͷίʔυ͸҆શͳ࣮૷͔ʁ

Slide 11

Slide 11 text

͜ͷ࣮૷͸εϨουηʔϑͰ͸ͳ͍ 11 class CoreDataController { private var entity: CoreDataEntity? = nil private let moc: NSManagedObjectContext init(container: NSPersistentContainer) { self.moc = container.newBackgroundContext() } func configure() throws { entity = CoreDataEntity(context: moc) try moc.save() } } initͱҟͳΔεϨου͔Β ΞΫηεͯ͠͸͍͚ͳ͍

Slide 12

Slide 12 text

͜ͷ࣮૷͸εϨουηʔϑͰ͸ͳ͍ 12 class CoreDataController { private var entity: CoreDataEntity? = nil private let moc: NSManagedObjectContext init(container: NSPersistentContainer) { self.moc = container.newBackgroundContext() } func configure() throws { entity = CoreDataEntity(context: moc) try moc.save() } } /4.BOBHFE0CKFDUͱ/4.BOBHFE0CKFDU$POUFYU͸ εϨουηʔϑͰ͸ͳ͍ɻ

Slide 13

Slide 13 text

͜ͷ࣮૷͸εϨουηʔϑͰ͸ͳ͍ 13 class CoreDataController { private var entity: CoreDataEntity? = nil private let moc: NSManagedObjectContext init(container: NSPersistentContainer) { self.moc = container.newBackgroundContext() } func configure() throws { entity = CoreDataEntity(context: moc) try moc.save() } } εϨουηʔϑͰ͸ͳ͍ΦϒδΣΫτΛ ϓϩύςΟͱͯ͠อ͍࣋ͯ͠Δɻ ˠҟͳΔεϨου͔ΒΞΫηε͢ΔͱεϨουҧ൓ /4.BOBHFE0CKFDUͱ/4.BOBHFE0CKFDU$POUFYU͸ εϨουηʔϑͰ͸ͳ͍ɻ

Slide 14

Slide 14 text

$PSF%BUBͷεϨουҧ൓ͱ͸ w /4.BOBHFE0CKFDUɺ/4.BOBHFE0CKFDU$POUFYU͸ ͦΕΛੜ੒ͨ͠εϨουͷ֎͔ΒΞΫηε͢ΔͱεϨουҧ൓ɻ w σʔλͷෆ੔߹΍ΫϥογϡΛҾ͖ى͜͢ɻ 14

Slide 15

Slide 15 text

$PSF%BUBͷεϨουҧ൓ͱ͸ w /4.BOBHFE0CKFDUɺ/4.BOBHFE0CKFDU$POUFYU͸ ͦΕΛੜ੒ͨ͠εϨουͷ֎͔ΒΞΫηε͢ΔͱεϨουҧ൓ɻ w σʔλͷෆ੔߹΍ΫϥογϡΛҾ͖ى͜͢ɻ w ͜ΕΒͷΦϒδΣΫτΛੜ੒ͨ͠εϨουͷ֎ʹ࣋ͪग़͞ͳ͍͜ͱ Λ"QQMFͷυΩϡϝϯτ͸ٻΊ͍ͯΔɻ 15 "QQMF%FWFMPQFS%PDVNFOUBUJPOʰ/4.BOBHFE0CKFDU$POUFYUʱΑΓ

Slide 16

Slide 16 text

"DUPSʹ͢Ε͹େৎ෉ʁ 16 actor CoreDataController { private var entity: CoreDataEntity? = nil private let moc: NSManagedObjectContext init(container: NSPersistentContainer) { self.moc = container.newBackgroundContext() } func configure() throws { entity = CoreDataEntity(context: moc) try moc.save() } }

Slide 17

Slide 17 text

17 w "DUPSʹ͢Ε͹σʔλڝ߹͠ͳ͍͸ͣʜ actor CoreDataController { private var entity: CoreDataEntity? = nil private let moc: NSManagedObjectContext init(container: NSPersistentContainer) { self.moc = container.newBackgroundContext() } func configure() throws { entity = CoreDataEntity(context: moc) try moc.save() } } "DUPSʹ͢Ε͹େৎ෉ʁ

Slide 18

Slide 18 text

18 w "DUPSʹ͢Ε͹σʔλڝ߹͠ͳ͍͸ͣʜ actor CoreDataController { private var entity: CoreDataEntity? = nil private let moc: NSManagedObjectContext init(container: NSPersistentContainer) { self.moc = container.newBackgroundContext() } func configure() throws { entity = CoreDataEntity(context: moc) try moc.save() } } ͜ͷ࣮૷͸$PODVSSFODZXBSOJOHΛग़͞ͳ͍ɻ "DUPSʹ͢Ε͹େৎ෉ʁ

Slide 19

Slide 19 text

actor CoreDataController { private var entity: CoreDataEntity? = nil private let moc: NSManagedObjectContext init(container: NSPersistentContainer) { self.moc = container.newBackgroundContext() } func configure() throws { entity = CoreDataEntity(context: moc) try moc.save() } } 19 w "DUPSCPVOEBSZ֎͔Β͜ͷBDUPSΛ࢖ͬͯΈΔɻ func testCallCoreDataController() async throws { let controller = CoreDataController( container: container ) try await controller.configure() } "DUPSʹ͢Ε͹େৎ෉ʁ

Slide 20

Slide 20 text

actor CoreDataController { private var entity: CoreDataEntity? = nil private let moc: NSManagedObjectContext init(container: NSPersistentContainer) { self.moc = container.newBackgroundContext() } func configure() throws { entity = CoreDataEntity(context: moc) try moc.save() } } 20 w ͜ͷ࣮૷͸εϨουҧ൓ΛҾ͖ى͜͢ɻ ͜͜ͰΫϥογϡ "DUPSʹ͢Ε͹େৎ෉ʁ

Slide 21

Slide 21 text

actor CoreDataController { private var entity: CoreDataEntity? = nil private let moc: NSManagedObjectContext init(container: NSPersistentContainer) { self.moc = container.newBackgroundContext() } func configure() throws { entity = CoreDataEntity(context: moc) try moc.save() } } "DUPS͸εϨουಉҰੑΛอূ͠ͳ͍ 21 w JOJUͱDPOpHVSF͕ݺ͹ΕΔεϨου͸ɺ࣮ࡍʹ͸ҟͳΔɻ func testCallCoreDataController() async throws { let controller = CoreDataController( container: container ) try await controller.configure() }

Slide 22

Slide 22 text

$PSF%BUBͷεϨουҧ൓ͱ͸ w /4.BOBHFE0CKFDUɺ/4.BOBHFE0CKFDU$POUFYU͸ ͦΕΛੜ੒ͨ͠εϨουͷ֎͔ΒΞΫηε͢ΔͱεϨουҧ൓ɻ w σʔλͷෆ੔߹΍ΫϥογϡΛҾ͖ى͜͢ɻ w ͜ΕΒͷΦϒδΣΫτΛੜ੒ͨ͠εϨουͷ֎ʹ࣋ͪग़͞ͳ͍͜ͱ Λ"QQMFͷυΩϡϝϯτ͸ٻΊ͍ͯΔɻ w "DUPS͸εϨουͷಉҰੑΛอূ͠ͳ͍ɻ w .BOBHFE0CKFDU౳͕ੜ੒εϨουͷ֎ʹ࣋ͪग़͞Εͯ͠·͏ɻ 22

Slide 23

Slide 23 text

εϨουҧ൓Λ๷͙ैདྷख๏ 23 w /4.BOBHFE0CKFDUͷ͔ΘΓʹ/4.BOBHFE0CKFDU*%Λ ϓϩύςΟͱͯ͠อ࣋͢Δɻ

Slide 24

Slide 24 text

class CoreDataController { private var entityID: NSManagedObjectID? = nil private let container: NSPersistentContainer func update(_ newName: String) async throws { guard let entityID else { return } let moc = container.newBackgroundContext() try await moc.perform { let entity = try? moc.existingObject(with: entityID) as? CoreDataEntity entity?.name = newName try moc.save() } } } /4.BOBHFE0CKFDU*%Λ࢖͏ 24

Slide 25

Slide 25 text

class CoreDataController { private var entityID: NSManagedObjectID? = nil private let container: NSPersistentContainer func update(_ newName: String) async throws { guard let entityID else { return } let moc = container.newBackgroundContext() try await moc.perform { let entity = try? moc.existingObject(with: entityID) as? CoreDataEntity entity?.name = newName try moc.save() } } } /4.BOBHFE0CKFDU*%Λ࢖͏ 25 ࣮ࡍͷNBOBHFEPCKFDUͷܕͷ͔ΘΓʹ /4.BOBHFE0CKFDU*%Λ࢖༻ .BOBHFEPCKFDUʹΞΫηε͢Δʹ͸GFUDI͢Δ

Slide 26

Slide 26 text

class CoreDataController { private var entityID: NSManagedObjectID? = nil private let container: NSPersistentContainer func update(_ newName: String) async throws { guard let entityID else { return } let moc = container.newBackgroundContext() try await moc.perform { let entity = try? moc.existingObject(with: entityID) as? CoreDataEntity entity?.name = newName try moc.save() } } } /4.BOBHFE0CKFDU*%Λ࢖͏ 26 .BOBHFE0CKFDUʹΞΫηε͢Δʹ͸ ຖճGFUDI͠ͳ͚Ε͹ͳΒͳ͍ .BOBHFE0CKFDUͷܕ৘ใ͕ͳ͍

Slide 27

Slide 27 text

εϨουҧ൓Λ๷͙ैདྷख๏ 27 w /4.BOBHFE0CKFDUͷ͔ΘΓʹ/4.BOBHFE0CKFDU*%ΛϓϩύςΟ ͱͯ͠อ࣋͢Δɻ w /4.BOBHFE0CKFDU*%ʹ͸ܕ৘ใ͕ͳ͍ɻ w .BOBHFEPCKFDUʹΞΫηε͢Δʹ͸౎౓GFUDIͤͶ͹ͳΒͳ͍ɻ

Slide 28

Slide 28 text

w /4.BOBHFE0CKFDUͷ͔ΘΓʹ/4.BOBHFE0CKFDU*%ΛϓϩύςΟ ͱͯ͠อ࣋͢Δɻ w /4.BOBHFE0CKFDU*%ʹ͸ܕ৘ใ͕ͳ͍ɻ w .BOBHFEPCKFDUʹΞΫηε͢Δʹ͸౎౓GFUDIͤͶ͹ͳΒͳ͍ɻ 28 4XJGU$PODVSSFODZͰ.BOBHFE0CKFDUΛ҆શʹอ͍࣋ͨ͠ʂ εϨουҧ൓Λ๷͙ैདྷख๏

Slide 29

Slide 29 text

.BOBHFE0CKFDUΛ ҆શʹอ࣋͢Δʹ͸ʁ 29

Slide 30

Slide 30 text

ඞཁͳੑ࣭ 4XJGU$PODVSSFODZʹ͓͍ͯ.BOBHFE0CKFDUΛ҆શʹϓϩύςΟͱ ͯ͠อ࣋ɺड͚౉͢͠Δʹ͸ɺ.BOBHFE0CKFDUͱ.BOBHFE 0CKFDU$POUFYUʢ.0$ʣ͕࣍ͷੑ࣭Λຬͨ͢ඞཁ͕͋Δɻ w 4FOEBCMFͰ͋Δɻ w .BOBHFE0CKFDU͸ൃߦݩͷ.0$ͱಉ͡εϨουͰΞΫηε͞ΕΔɻ 30

Slide 31

Slide 31 text

ඞཁͳੑ࣭ 4XJGU$PODVSSFODZʹ͓͍ͯ.BOBHFE0CKFDUΛ҆શʹϓϩύςΟͱ ͯ͠อ࣋ɺड͚౉͢͠Δʹ͸ɺ.BOBHFE0CKFDUͱ.BOBHFE 0CKFDU$POUFYUʢ.0$ʣ͕࣍ͷੑ࣭Λຬͨ͢ඞཁ͕͋Δɻ w 4FOEBCMFͰ͋Δɻ w .BOBHFE0CKFDU͸ൃߦݩͷ.0$ͱಉ͡εϨουͰΞΫηε͞ΕΔɻ 31

Slide 32

Slide 32 text

4FOEBCMFͱ͸ʁ w σʔλڝ߹͕ൃੜͤͣ҆શʹड͚౉͠Ͱ͖ΔܕΛද͢ϓϩτίϧɻ w ͲͷBDUPSDPOUFYU͔ΒΞΫηεͯ͠΋҆શɻ 32

Slide 33

Slide 33 text

4FOEBCMFͱ͸ʁ w σʔλڝ߹͕ൃੜͤͣ҆શʹड͚౉͠Ͱ͖ΔܕΛද͢ϓϩτίϧɻ w ͲͷBDUPSDPOUFYU͔ΒΞΫηεͯ͠΋҆શɻ w ྫ͑͹ɺ஋ܕ͸4FOEBCMFɻ w ड͚౉࣌͠ʹίϐʔ͞ΕΔ͔Βɻ w /4.BOBHFE0CKFDU΍/4.BOBHFE0CKFDU$POUFYU͸ 4FOEBCMFͰͳ͍ɻ w ҟͳΔBDUPSDPOUFYU͔ΒΞΫηεͯ͠͸͍͚ͳ͍ɻ 33

Slide 34

Slide 34 text

ඞཁͳੑ࣭ 4XJGU$PODVSSFODZʹ͓͍ͯ.BOBHFE0CKFDUΛ҆શʹϓϩύςΟͱ ͯ͠อ࣋ɺड͚౉͢͠Δʹ͸ɺ.BOBHFE0CKFDUͱ.BOBHFE 0CKFDU$POUFYUʢ.0$ʣ͕࣍ͷੑ࣭Λຬͨ͢ඞཁ͕͋Δɻ w 4FOEBCMFͰ͋Δɻ w .BOBHFE0CKFDU͸ൃߦݩͷ.0$ͱಉ͡εϨουͰΞΫηε͞ΕΔɻ 34

Slide 35

Slide 35 text

ඞཁͳੑ࣭ 4XJGU$PODVSSFODZʹ͓͍ͯ.BOBHFE0CKFDUΛ҆શʹϓϩύςΟͱ ͯ͠อ࣋ɺड͚౉͢͠Δʹ͸ɺ.BOBHFE0CKFDUͱ.BOBHFE 0CKFDU$POUFYUʢ.0$ʣ͕࣍ͷੑ࣭Λຬͨ͢ඞཁ͕͋Δɻ w 4FOEBCMFͰ͋Δɻ w (MPCBMBDUPSΛܕʹద༻͢Δɻ w .BOBHFE0CKFDU͸ൃߦݩͷ.0$ͱಉ͡εϨουͰΞΫηε͞ΕΔɻ 35

Slide 36

Slide 36 text

(MPCBMBDUPSͱ͸ʁ w ϓϩύςΟ౳΁ͷಉظΞΫηεΛಛఆͷBDUPSDPOUFYUʹ੍ݶ͢Δɻ w ྫʣ.BJO"DUPSΛద༻ͨ͠ϓϩύςΟ͸ɺ.BJO"DUPS͔ΒͷΈ ಉظΞΫηεͰ͖Δɻ w /PO4FOEBCMFͳܕʹHMPCBMBDUPSΛద༻͢Δͱɺ4FOEBCMFͳܕ ͱͯ͠ѻ͏͜ͱ͕Ͱ͖Δɻ w (MPCBMBDUPSʹΑͬͯσʔλڝ߹͕ൃੜ͠ͳ͍͜ͱ͕อূ͞ΕΔ͔Βɻ 36 @MainActor var mainActorIsolatedValue: Int?

Slide 37

Slide 37 text

(MPCBMBDUPSΛఆٛ͢Δ w .BOBHFE0CKFDU΍.0$Λ4FOEBCMFʹ͢ΔͨΊʹ HMPCBMBDUPSΛఆٛ͢Δɻ w (MPCBMBDUPSͱͯ͠ɺ$PSF%BUB"DUPSΛఆٛ͢Δɻ w 6*΁ͷӨڹΛ๷͙ͨΊɺ.BJO"DUPS͸࢖Θͳ͍ɻ 37 @globalActor public actor CoreDataActor { public static let shared = CoreDataActor() }

Slide 38

Slide 38 text

.BOBHFE0CKFDUʹHMPCBMBDUPSΛద༻ w .BOBHFE0CKFDUͷܕʢ$PSF%BUB&OUJUZʣʹ$PSF%BUB"DUPSΛ ద༻͢Δɻ w ܕͷఆٛʹ!$PSF%BUB"DUPSΛ͚ͭΔ͚ͩɻ w ͜ΕͰ.BOBHFE0CKFDUΛ4FOEBCMFͳ΋ͷͱͯ͠ѻ͑Δɻ 38 @objc(CoreDataEntity) @CoreDataActor public class CoreDataEntity: NSManagedObject {}

Slide 39

Slide 39 text

.0$ʹHMPCBMBDUPSΛద༻ w $PSF%BUB"DUPSΛద༻ͨ͠ϥού $".BOBHFE0CKFDU$POUFYU Λ༻ҙ͠ɺϥούܦ༝Ͱ.0$Λར༻͢Δɻ 39 @CoreDataActor final class CAManagedObjectContext { private let moc: NSManagedObjectContext init(_ moc: NSManagedObjectContext) { self.moc = moc } func fetch<…>(…) throws -> [T] { … } func save() throws { try moc.save() } func delete(_ object: NSManagedObject) { … } func insert() -> T { … } }

Slide 40

Slide 40 text

ඞཁͳੑ࣭ 4XJGU$PODVSSFODZʹ͓͍ͯ.BOBHFE0CKFDUΛ҆શʹϓϩύςΟͱ ͯ͠อ࣋ɺड͚౉͢͠Δʹ͸ɺ.BOBHFE0CKFDUͱ.BOBHFE 0CKFDU$POUFYUʢ.0$ʣ͕࣍ͷੑ࣭Λຬͨ͢ඞཁ͕͋Δɻ w 4FOEBCMFͰ͋Δɻ w (MPCBMBDUPSΛܕʹద༻͢Δɻ w .BOBHFE0CKFDU͸ൃߦݩͷ.0$ͱಉ͡εϨουͰΞΫηε͞ΕΔɻ 40

Slide 41

Slide 41 text

ඞཁͳੑ࣭ 4XJGU$PODVSSFODZʹ͓͍ͯ.BOBHFE0CKFDUΛ҆શʹϓϩύςΟͱ ͯ͠อ࣋ɺड͚౉͢͠Δʹ͸ɺ.BOBHFE0CKFDUͱ.BOBHFE 0CKFDU$POUFYUʢ.0$ʣ͕࣍ͷੑ࣭Λຬͨ͢ඞཁ͕͋Δɻ w 4FOEBCMFͰ͋Δɻ w (MPCBMBDUPSΛܕʹద༻͢Δɻ w .BOBHFE0CKFDU͸ൃߦݩͷ.0$ͱಉ͡εϨουͰΞΫηε͞ΕΔɻ 41

Slide 42

Slide 42 text

ඞཁͳੑ࣭ 4XJGU$PODVSSFODZʹ͓͍ͯ.BOBHFE0CKFDUΛ҆શʹϓϩύςΟͱ ͯ͠อ࣋ɺड͚౉͢͠Δʹ͸ɺ.BOBHFE0CKFDUͱ.BOBHFE 0CKFDU$POUFYUʢ.0$ʣ͕࣍ͷੑ࣭Λຬͨ͢ඞཁ͕͋Δɻ w 4FOEBCMFͰ͋Δɻ w (MPCBMBDUPSΛܕʹద༻͢Δɻ w .BOBHFE0CKFDU͸ൃߦݩͷ.0$ͱಉ͡εϨουͰΞΫηε͞ΕΔɻ w $VTUPN"DUPS&YFDVUPSΛར༻͢Δɻ 42

Slide 43

Slide 43 text

"DUPSͷ࣮ߦ؀ڥ 43 actor MyActor { … } w "DUPS͸ɺσʔλڝ߹͕ൃੜ͠ͳ͍͜ͱΛอূ͢Δɻ w ಉظతʹ࣮ߦ͢Δ໋ྩͷ·ͱ·ΓͰ͋Δʮ+PCʯΛҰ࣮ͭͣͭߦɻ

Slide 44

Slide 44 text

"DUPSͷ࣮ߦ؀ڥ 44 actor MyActor { … } w "DUPS͸ɺσʔλڝ߹͕ൃੜ͠ͳ͍͜ͱΛอূ͢Δɻ w ಉظతʹ࣮ߦ͢Δ໋ྩͷ·ͱ·ΓͰ͋Δʮ+PCʯΛҰ࣮ͭͣͭߦɻ w ʮ+PCʯΛͲͷΑ͏ʹ࣮ߦ͢Δ͔͸ఆٛ͞Ε͍ͯͳ͍ɻ w σϑΥϧτͰ͸ɺ4XJGUϥϯλΠϜ͕+PCͷ࣮ߦ؀ڥΛఏڙ͢Δɻ w +PC͕࣮ߦ͞ΕΔεϨουࣗମ͸ຖճมΘΔՄೳੑ͕͋Δɻ

Slide 45

Slide 45 text

$VTUPN"DUPS&YFDVUPSͱ͸ w 4& 4XJGUͰ࣮૷ w "DUPSͷʮ+PCΛͲ͏࣮ߦ͢Δͷ͔ʯΛΧελϚΠζͰ͖Δɻ w +PCΛ࣮ߦ͢Δ&YFDVUPSΛ࣮૷͢Δɻ w VOPXOFE&YFDVUPSͱͯ͠ɺ+PCΛ࣮ߦ͢Δ&YFDVUPSΛొ࿥͢Δɻ 45 actor MyActor { nonisolated var unownedExecutor: UnownedSerialExecutor { ... } }

Slide 46

Slide 46 text

ͲΜͳ&YFDVUPSΛ࣮૷͢΂͖͔ w /4.BOBHFE0CKFDU$POUFYUQFSGPSN಺ͰॲཧΛߦ͍͍ͨɻ w NBOBHFEPCKFDUDPOUFYUΛอ࣋͢Δɻ w NBOBHFEPCKFDUDPOUFYUͷQFSGPSNͰ+PCΛશ࣮ͯߦ͢Δɻ w 4IBSFEΠϯελϯε͕ඞཁɻ w (MPCBMBDUPSʹొ࿥͢Δɻ 46

Slide 47

Slide 47 text

$PSF%BUB&YFDVUPSͷ࣮૷ w KPCΛ/4.BOBHFE0CKFDU$POUFYUQFSGPSN @ Ͱ࣮ߦ͢Δɻ 47 final class CoreDataExecutor: SerialExecutor { private let container: MOCContainer func enqueue(_ job: consuming ExecutorJob) { let unownedJob = UnownedJob(job) container.perform { unownedJob.runSynchronously( on: self.asUnownedSerialExecutor() ) } } }

Slide 48

Slide 48 text

$PSF%BUB&YFDVUPSͷ࣮૷ 48 final class CoreDataExecutor: SerialExecutor { private let container: MOCContainer func enqueue(_ job: consuming ExecutorJob) { let unownedJob = UnownedJob(job) container.perform { unownedJob.runSynchronously( on: self.asUnownedSerialExecutor() ) } } } w KPCΛ/4.BOBHFE0CKFDU$POUFYUQFSGPSN @ Ͱ࣮ߦ͢Δɻ +PCΛQFSGPSNؔ਺಺Ͱ࣮ߦ

Slide 49

Slide 49 text

$PSF%BUB&YFDVUPSͷ࣮૷ 49 final class CoreDataExecutor: SerialExecutor { private let container: MOCContainer func enqueue(_ job: consuming ExecutorJob) { let unownedJob = UnownedJob(job) container.perform { unownedJob.runSynchronously( on: self.asUnownedSerialExecutor() ) } } } w KPCΛ/4.BOBHFE0CKFDU$POUFYUQFSGPSN @ Ͱ࣮ߦ͢Δɻ &YFDVUPS+PC͸/PODPQZBCMFUZQF ʢ4XJGUͰಋೖʣ

Slide 50

Slide 50 text

$PSF%BUB&YFDVUPSͷ࣮૷ 50 final class CoreDataExecutor: SerialExecutor { private let container: MOCContainer func enqueue(_ job: consuming ExecutorJob) { let unownedJob = UnownedJob(job) container.perform { unownedJob.runSynchronously( on: self.asUnownedSerialExecutor() ) } } } w 4FSJBM&YFDVUPS͸4FOEBCMFͰ͋Δ͜ͱΛཁٻ͢Δɻ /4.BOBHFE0CKFDU$POUFYUΛ 4FOEBCMFͳ΋ͷͱͯ͠ѻ͏ͨΊͷίϯςφ

Slide 51

Slide 51 text

.0$$POUBJOFSͷ࣮૷ w .0$ͷQFSGPSNΛεϨουηʔϑʹݺͿͨΊͷίϯςφ 51 final class MOCContainer: @unchecked Sendable { private let persistentContainer: NSPersistentContainer let queue = DispatchQueue(label: "MOCContainer") lazy var moc: NSManagedObjectContext = persistentContainer.newBackgroundContext() init(_ persistentContainer: NSPersistentContainer) { self.persistentContainer = persistentContainer } func perform(_ block: @escaping @Sendable () -> Void) { queue.async { self.moc.perform(block) } } }

Slide 52

Slide 52 text

$PSF%BUB&YFDVUPS͖ͭͮ w (MPCBMBDUPSʹ&YFDVUPSΛొ࿥͢ΔͨΊʹɺTIBSFEΠϯελϯεΛ ༻ҙ͢Δɻ 52 extension CoreDataExecutor { @CoreDataActor var moc: CAManagedObjectContext { .init(container.moc) } static var sharedExecutor = CoreDataExecutor.init(.shared) static var sharedUnownedExecutor: UnownedSerialExecutor { sharedExecutor.asUnownedSerialExecutor() } }

Slide 53

Slide 53 text

(MPCBMBDUPSʹ&YFDVUPSΛొ࿥ w $PSF%BUB"DUPSͷVOPXOFE&YFDVUPSͱͯ͠ɺ $PSF%BUB&YFDVUPSͷTIBSFEΠϯελϯεΛฦ͢Α͏ʹ͢Δɻ w $PSF%BUB"DUPSʹର͢Δૢ࡞͸͢΂ͯɺ$PSF%BUB&YFDVUPS͕؅ཧ ͢Δ.0$ͷQFSGPSNؔ਺Ͱ࣮ߦ͞ΕΔΑ͏ʹͳͬͨɻ 53 extension CoreDataActor { public nonisolated var unownedExecutor: UnownedSerialExecutor { CoreDataExecutor.sharedUnownedExecutor } }

Slide 54

Slide 54 text

͜͜·Ͱͷ·ͱΊ .BOBHFE0CKFDUͱ.0$ʹରͯ͠ҎԼͷ͜ͱΛߦͳͬͨɻ w 4FOEBCMFʹ͢Δɻ w .BOBHFE0CKFDUʜ(MPCBMBDUPSΛܕʹద༻͢Δɻ w .0$ʜ(MPCBMBDUPSΛద༻ͨ͠ϥούΛ࣮૷ɻ w (MPCBMBDUPSͷ+PCͷ࣮ߦΛ੍ݶɻ w $VTUPN"DUPS&YFDVUPSΛར༻͢Δɻ w &YFDVUPSͷڞ௨.0$ͷQFSGPSNؔ਺Ͱ͢΂ͯͷ+PCΛ࣮ߦɻ 54

Slide 55

Slide 55 text

͜͜·Ͱͷ·ͱΊ .BOBHFE0CKFDUͱ.0$ʹରͯ͠ҎԼͷ͜ͱΛߦͳͬͨɻ w 4FOEBCMFʹ͢Δɻ w .BOBHFE0CKFDUʜ(MPCBMBDUPSΛܕʹద༻͢Δɻ w .0$ʜ(MPCBMBDUPSΛద༻ͨ͠ϥούΛ࣮૷ɻ w (MPCBMBDUPSͷ+PCͷ࣮ߦΛ੍ݶɻ w $VTUPN"DUPS&YFDVUPSΛར༻͢Δɻ w &YFDVUPSͷڞ௨.0$ͷQFSGPSNؔ਺Ͱ͢΂ͯͷ+PCΛ࣮ߦɻ 55

Slide 56

Slide 56 text

͜͜·Ͱͷ·ͱΊ .BOBHFE0CKFDUͱ.0$ʹରͯ͠ҎԼͷ͜ͱΛߦͳͬͨɻ w 4FOEBCMFʹ͢Δɻ w .BOBHFE0CKFDUʜ(MPCBMBDUPSΛܕʹద༻͢Δɻ w .0$ʜ(MPCBMBDUPSΛద༻ͨ͠ϥούΛ࣮૷ɻ w (MPCBMBDUPSͷ+PCͷ࣮ߦΛ੍ݶɻ w $VTUPN"DUPS&YFDVUPSΛར༻͢Δɻ w &YFDVUPSͷڞ௨.0$ͷQFSGPSNؔ਺Ͱ͢΂ͯͷ+PCΛ࣮ߦɻ 56

Slide 57

Slide 57 text

͜ΕͰεϨουηʔϑʹͳͬͨͷ͔ʁ ࠷΋جຊతͳ$36%ૢ࡞ͦΕͧΕʹ͍ͭͯɺ w $PSF%BUB"DUPS಺͔ΒͷΞΫηε w $PSF%BUB"DUPS֎͔ΒͷΞΫηε ͷ৔߹ʹɺͲͷΑ͏ʹίϯύΠϥʹνΣοΫ͞ΕΔ͔Λݟ͍ͯ͘ɻ 57

Slide 58

Slide 58 text

$SFBUFૢ࡞ʢ$PSF%BUB"DUPS಺ʣ w .0$͸ɺ$PSF%BUB&YFDVUPS͕ఏڙ͢Δ $".BOBHFE0CKFDU$POUFYUΦϒδΣΫτΛ༻͍Δɻ w $PSF%BUB"DUPS಺ͳͷͰɺಉظతʹૢ࡞Ͱ͖Δɻ 58 @CoreDataActor func createObject() throws -> Entity { let moc = CoreDataExecutor.sharedExecutor.moc let managedObject: Entity = moc.insert() try moc.save() return managedObject }

Slide 59

Slide 59 text

@AnotherActor func createObject() throws -> Entity { let moc = CoreDataExecutor.sharedExecutor.moc let managedObject: Entity = moc.insert() try moc.save() return managedObject } $SFBUFૢ࡞ʢ$PSF%BUB"DUPS֎ʣ 59 ίϯύΠϧΤϥʔ BXBJU͕ඞཁ w .BOBHFEPCKFDU͓Αͼ.0$͸ɺඇಉظΞΫηε͕ڧ੍͞ΕΔ

Slide 60

Slide 60 text

$SFBUFૢ࡞ʢ$PSF%BUB"DUPS֎ʣ 60 @AnotherActor func createObject() async throws -> Entity { let moc = await CoreDataExecutor.sharedExecutor.moc let managedObject: Entity = await moc.insert() try await moc.save() return managedObject } w .BOBHFEPCKFDU͓Αͼ.0$͸ɺඇಉظΞΫηε͕ڧ੍͞ΕΔ

Slide 61

Slide 61 text

3FBEૢ࡞ʢ$PSF%BUB"DUPS಺ʣ 61 @CoreDataActor func fetchObject() throws -> Entity? { let moc = CoreDataExecutor.sharedExecutor.moc let fetchRequest = Entity.fetchRequest() fetchRequest.entity = Entity.entity() let managedObjects = try moc.fetch(fetchRequest) return managedObjects.first } w .0$͸ɺ$PSF%BUB&YFDVUPS͕ఏڙ͢Δ $".BOBHFE0CKFDU$POUFYUΦϒδΣΫτΛ༻͍Δɻ w $PSF%BUB"DUPS಺ͳͷͰɺಉظతʹૢ࡞Ͱ͖Δɻ

Slide 62

Slide 62 text

3FBEૢ࡞ʢ$PSF%BUB"DUPS֎ʣ w /4'FUDI3FRVFTU͸4FOEBCMFͰͳ͍ɻ w $PSF%BUB"DUPS಺Ͱ૊Έཱͯ.0$ʹ౉͢͜ͱ͕ඞཁɻ 62 @AnotherActor func fetchObject() async throws -> Entity? { let moc = await CoreDataExecutor.sharedExecutor.moc let managedObjects = try await Task { @CoreDataActor in let fetchRequest = Entity.fetchRequest() fetchRequest.entity = Entity.entity() return try moc.fetch(fetchRequest) }.value return managedObjects.first }

Slide 63

Slide 63 text

6QEBUFૢ࡞ʢ$PSF%BUB"DUPS಺ʣ 63 @CoreDataActor func updateObject(managedObject: Entity) throws { // nameΛupdate͢Δ let moc = CoreDataExecutor.sharedExecutor.moc managedObject.name = "Jiro" try moc.save() } w .0$͸ɺ$PSF%BUB&YFDVUPS͕ఏڙ͢Δ $".BOBHFE0CKFDU$POUFYUΦϒδΣΫτΛ༻͍Δɻ w $PSF%BUB"DUPS಺ͳͷͰɺಉظతʹૢ࡞Ͱ͖Δɻ

Slide 64

Slide 64 text

6QEBUFૢ࡞ʢ$PSF%BUB"DUPS֎ʣ w 4FUUFS͸BDUPS֎ʹެ։͞Εͳ͍ͨΊɺ$PSF%BUB"DUPS಺Ͱͷૢ࡞ ͕ڧ੍͞ΕΔɻ 64 @AnotherActor func updateObject(managedObject: Entity) async throws { // nameΛupdate͢Δ try await Task { @CoreDataActor in let moc = CoreDataExecutor.sharedExecutor.moc managedObject.name = "Jiro" try moc.save() }.value }

Slide 65

Slide 65 text

%FMFUFૢ࡞ʢ$PSF%BUB"DUPS಺ʣ 65 @CoreDataActor func deleteObject(managedObject: Entity) throws { let moc = CoreDataExecutor.sharedExecutor.moc moc.delete(managedObject) try moc.save() } w .0$͸ɺ$PSF%BUB&YFDVUPS͕ఏڙ͢Δ $".BOBHFE0CKFDU$POUFYUΦϒδΣΫτΛ༻͍Δɻ w $PSF%BUB"DUPS಺ͳͷͰɺಉظతʹૢ࡞Ͱ͖Δɻ

Slide 66

Slide 66 text

%FMFUFૢ࡞ʢ$PSF%BUB"DUPS֎ʣ 66 @AnotherActor func deleteObject(managedObject: Entity) async throws { let moc = await CoreDataExecutor.sharedExecutor.moc await moc.delete(managedObject) try await moc.save() } w .BOBHFEPCKFDU͓Αͼ.0$͸ɺඇಉظΞΫηε͕ڧ੍͞ΕΔ

Slide 67

Slide 67 text

࠷ॳͷίʔυ͸Ͳ͏ͳͬͨͷ͔ 67 class CoreDataController { private var entity: CoreDataEntity? = nil private let moc: NSManagedObjectContext init(container: NSPersistentContainer) { self.moc = container.newBackgroundContext() } func configure() throws { entity = CoreDataEntity(context: moc) try moc.save() } }

Slide 68

Slide 68 text

͜͏ͳΓ·ͨ͠ 68 @CoreDataActor class CoreDataController { private var entity: CoreDataEntity? = nil func configure() throws { let moc = CoreDataExecutor.sharedExecutor.moc entity = moc.insert() try moc.save() } }

Slide 69

Slide 69 text

͜͏ͳΓ·ͨ͠ 69 @CoreDataActor class CoreDataController { private var entity: CoreDataEntity? = nil func configure() throws { let moc = CoreDataExecutor.sharedExecutor.moc entity = moc.insert() try moc.save() } } w $MBTTࣗମΛ$PSF%BUB"DUPSʹॴଐͤ͞Δɻ w ҆શʹNBOBHFEPCKFDUΛϓϩύςΟͱͯ͠อ࣋ɻ

Slide 70

Slide 70 text

·ͱΊ w NBOBHFEPCKFDUͱNBOBHFEPCKFDUDPOUFYUΛɺHMPCBMBDUPS Λ༻͍ͯεϨουηʔϑʹ͢Δ͜ͱΛࢼΈͨɻ w $VTUPNBDUPSFYFDVUPSΛར༻͢Δ͜ͱͰɺ࣮ߦεϨουͷಉҰ ੑΛ࣮ݱͰ͖Δɻ w $36%ૢ࡞ʹ͍ͭͯɺBDUPSڥք಺͔Β͸શͯಉظతʹૢ࡞͕Մೳͳ ҰํͰɺBDUPSڥք֎͔Β͸ඇಉظΞΫηεΛཁٻͰ͖ͨɻ 70