wxr
2023-06-06 592974441a4df95fffd9167c90192da1a390b1c2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
///*
//See LICENSE folder for this sample’s licensing information.
 
//Abstract:
//A data manager that manages data conforming to `Codable` and stores it in `UserDefaults`.
//*/
 
//using System;
//using Foundation;
//using CoreFoundation;
 
//namespace SiriKit
//{
//    public struct UserDefaultsStorageDescriptor
//    {
//        public string Key { get; set; }
//        public UserDefaultsStorageDescriptor(string key)
//        {
//            Key = key;
//        }
//    }
 
//    public static class NotificationKeys
//    {
//        // Clients of `DataManager` that want to know when the data changes can 
//        // listen for this notification.
//        public const string DataChanged = "DataChangedNotification";
//    }
 
//    public class DataManager<ManagedDataType> : NSObject 
//        where ManagedDataType : NSObject, INSCoding
//    {
//        // This sample uses App Groups to share a suite of data between the 
//        // main app and the different extensions.
//        protected NSUserDefaults UserDefaults = NSUserDefaultsHelper.DataSuite;
 
//        // To prevent data races, all access to `UserDefaults` uses this queue.
//        protected DispatchQueue UserDefaultsAccessQueue = new DispatchQueue("User Defaults Access Queue");
 
//        // Storage and observation information.
//        protected UserDefaultsStorageDescriptor StorageDescriptor;
 
//        // A flag to avoid receiving notifications about data this instance just 
//        // wrote to `UserDefaults`.
//        protected bool IgnoreLocalUserDefaultsChanges = false;
 
//        // The observer object handed back after registering to observe a 
//        // property.
//        IDisposable UserDefaultsObserver;
 
//        // The data managed by this `DataManager`.
//        //此“DataManager”管理的数据。
//        protected ManagedDataType ManagedDataBackingInstance;
 
//        // Access to `managedDataBackingInstance` needs to occur on a dedicated 
//        // queue to avoid data races.
//        protected DispatchQueue DataAccessQueue = new DispatchQueue("Data Access Queue");
 
//        // Public access to the managed data for clients of `DataManager`
//        public ManagedDataType ManagedData
//        {
//            get
//            {
//                ManagedDataType data = null;
//                DataAccessQueue.DispatchSync(() => data = ManagedDataBackingInstance);
//                return data;
//            }
//        }
 
//        // See note below about createInitialData and initialData
//        public DataManager(UserDefaultsStorageDescriptor storageDescriptor, ManagedDataType initialData)
//        {
//            StorageDescriptor = storageDescriptor;
//            LoadData();
//            if (ManagedDataBackingInstance is null)
//            {
//                ManagedDataBackingInstance = initialData;
//                WriteData();
//            }
//            ObserveChangesInUserDefaults();
//        }
 
//        // createInitialData
//        //
//        // The Swift version of this app has a createInitialData method.
//        // Each child class of the DataManager class overrides this method, and
//        // then the DataManager base class calls the derived versions to get
//        // the initial data. C# gives a compiler warning for this ("Virtual
//        // member call in constructor"). Since in C# the base class constructor
//        // is run before the child class constructor, having the base clas
//        // constructor call out to a method on the derived class is calling
//        // a method on an object that has not yet been fully constructed.
//        // The C# version of this sample works around this problem by passing 
//        // in the initial data to the constructor.
 
//        void ObserveChangesInUserDefaults()
//        {
//            var weakThis = new WeakReference<DataManager<ManagedDataType>>(this);
//            Action<NSObservedChange> changeHandler = (change) =>
//            {
//                if (weakThis.TryGetTarget(out var dataManager))
//                {
//                    // Ignore any change notifications coming from data this 
//                    // instance just saved to `NSUserDefaults`.
//                    if (dataManager is null || dataManager.IgnoreLocalUserDefaultsChanges)
//                    {
//                        return;
//                    }
 
//                    // The underlying data changed in `NSUserDefaults`, so 
//                    // update this instance with the change and notify clients 
//                    // of the change.
//                    dataManager.LoadData();
//                    dataManager.NotifyClientsDataChanged();
//                }
//            };
//            UserDefaultsObserver = UserDefaults.AddObserver(
//                StorageDescriptor.Key,
//                NSKeyValueObservingOptions.Initial | NSKeyValueObservingOptions.New,
//                changeHandler
//            );
//        }
 
//        // Notifies clients the data changed by posting an `NSNotification` with 
//        // the key `NotificationKeys.DataChanged`
//        void NotifyClientsDataChanged()
//        {
//            var notification = NSNotification.FromName(NotificationKeys.DataChanged, this);
//            NSNotificationCenter.DefaultCenter.PostNotification(notification);
//        }
 
//        protected virtual void FinishUnarchiving(NSObject unarchivedData)
//        {
//            throw new NotImplementedException();
//        }
 
//        // Loads the data from `NSUserDefaults`.
//        void LoadData()
//        {
//            UserDefaultsAccessQueue.DispatchSync(() =>
//            {
//                NSData archivedData = UserDefaults.DataForKey(StorageDescriptor.Key);
//                try
//                {
//                    // Let the derived classes handle the specifics of 
//                    // putting the unarchived data in the correct format.
//                    // This is necessary because the derived classes
//                    // (SoupMenuManager, SoupOrderMenuManager) are using
//                    // generic data formats (NSMutableSet<T> or NSMutableArray<T>) 
//                    // and these types cannot be casted directly from the 
//                    // deserialized data.
//                    NSObject unarchivedData = NSKeyedUnarchiver.UnarchiveObject(archivedData);
//                    FinishUnarchiving(unarchivedData);
//                }
//                catch (Exception e)
//                {
//                    if (!(e is null))
//                    {
//                        Console.WriteLine($"Error: {e.Message}");
//                    }
//                }
//            });
//        }
 
//        // Writes the data to `NSUserDefaults`
//        protected void WriteData()
//        {
//            UserDefaultsAccessQueue.DispatchAsync(() =>
//            {
//                try
//                {
//                    NSData encodedData = NSKeyedArchiver.ArchivedDataWithRootObject(ManagedDataBackingInstance);
//                    IgnoreLocalUserDefaultsChanges = true;
//                    UserDefaults.SetValueForKey(encodedData, (NSString)StorageDescriptor.Key);
//                    IgnoreLocalUserDefaultsChanges = false;
//                    NotifyClientsDataChanged();
//                }
//                catch (Exception e)
//                {
//                    throw new Exception($"Could not save data. Reason: {e.Message}");
//                }
//            });
//        }
 
 
 
//    }
//}