X-Git-Url: https://git.mdrn.pl/wl-app.git/blobdiff_plain/53b27422d140022594fc241cca91c3183be57bca..48b2fe9f7c2dc3d9aeaaa6dbfb27c7da4f3235ff:/iOS/Pods/Realm/include/RLMObservation.hpp diff --git a/iOS/Pods/Realm/include/RLMObservation.hpp b/iOS/Pods/Realm/include/RLMObservation.hpp new file mode 100644 index 0000000..0f5b215 --- /dev/null +++ b/iOS/Pods/Realm/include/RLMObservation.hpp @@ -0,0 +1,153 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2015 Realm Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////// + +#import + +#import "binding_context.hpp" + +#import +#import + +#import + +@class RLMObjectBase, RLMRealm, RLMSchema, RLMProperty, RLMObjectSchema; +class RLMClassInfo; +class RLMSchemaInfo; + +namespace realm { + class History; + class SharedGroup; +} + +// RLMObservationInfo stores all of the KVO-related data for RLMObjectBase and +// RLMArray. There is a one-to-one relationship between observed objects and +// RLMObservationInfo instances, so it could be folded into RLMObjectBase, and +// is a separate class mostly to avoid making all accessor objects far larger. +// +// RLMClassInfo stores a vector of pointers to the first observation info +// created for each row. If there are multiple observation infos for a single +// row (such as if there are multiple observed objects backed by a single row, +// or if both an object and an array property of that object are observed), +// they're stored in an intrusive doubly-linked-list in the `next` and `prev` +// members. This is done primarily to make it simpler and faster to loop over +// all of the observed objects for a single row, as that needs to be done for +// every change. +class RLMObservationInfo { +public: + RLMObservationInfo(id object); + RLMObservationInfo(RLMClassInfo &objectSchema, std::size_t row, id object); + ~RLMObservationInfo(); + + realm::Row const& getRow() const { + return row; + } + + NSString *columnName(size_t col) const noexcept; + + // Send willChange/didChange notifications to all observers for this object/row + // Sends the array versions if indexes is non-nil, normal versions otherwise + void willChange(NSString *key, NSKeyValueChange kind=NSKeyValueChangeSetting, NSIndexSet *indexes=nil) const; + void didChange(NSString *key, NSKeyValueChange kind=NSKeyValueChangeSetting, NSIndexSet *indexes=nil) const; + + bool isForRow(size_t ndx) const { + return row && row.get_index() == ndx; + } + + void recordObserver(realm::Row& row, RLMClassInfo *objectInfo, RLMObjectSchema *objectSchema, NSString *keyPath); + void removeObserver(); + bool hasObservers() const { return observerCount > 0; } + + // valueForKey: on observed object and array properties needs to return the + // same object each time for KVO to work at all. Doing this all the time + // requires some odd semantics to avoid reference cycles, so instead we do + // it only to the extent specifically required by KVO. In addition, we + // need to continue to return the same object even if this row is deleted, + // or deleting an object with active observers will explode horribly. + // Once prepareForInvalidation() is called, valueForKey() will always return + // the cached value for object and array properties without checking the + // backing row to verify it's up-to-date. + // + // prepareForInvalidation() must be called on the head of the linked list + // (i.e. on the object pointed to directly by the object schema) + id valueForKey(NSString *key); + + void prepareForInvalidation(); + +private: + // Doubly-linked-list of observed objects for the same row as this + RLMObservationInfo *next = nullptr; + RLMObservationInfo *prev = nullptr; + + // Row being observed + realm::Row row; + RLMClassInfo *objectSchema = nullptr; + + // Object doing the observing + __unsafe_unretained id object = nil; + + // valueForKey: hack + bool invalidated = false; + size_t observerCount = 0; + NSString *lastKey = nil; + __unsafe_unretained RLMProperty *lastProp = nil; + + // objects returned from valueForKey() to keep them alive in case observers + // are added and so that they can still be accessed after row is detached + NSMutableDictionary *cachedObjects; + + void setRow(realm::Table &table, size_t newRow); + + template + void forEach(F&& f) const { + // The user's observation handler may release their last reference to + // the object being observed, which will result in the RLMObservationInfo + // being destroyed. As a result, we need to retain the object which owns + // both `this` and the current info we're looking at. + __attribute__((objc_precise_lifetime)) id self = object, current; + for (auto info = prev; info; info = info->prev) { + current = info->object; + f(info->object); + } + for (auto info = this; info; info = info->next) { + current = info->object; + f(info->object); + } + } + + // Default move/copy constructors don't work due to the intrusive linked + // list and we don't need them + RLMObservationInfo(RLMObservationInfo const&) = delete; + RLMObservationInfo(RLMObservationInfo&&) = delete; + RLMObservationInfo& operator=(RLMObservationInfo const&) = delete; + RLMObservationInfo& operator=(RLMObservationInfo&&) = delete; +}; + +// Get the the observation info chain for the given row +// Will simply return info if it's non-null, and will search ojectSchema's array +// for a matching one otherwise, and return null if there are none +RLMObservationInfo *RLMGetObservationInfo(RLMObservationInfo *info, size_t row, RLMClassInfo& objectSchema); + +// delete all objects from a single table with change notifications +void RLMClearTable(RLMClassInfo &realm); + +// invoke the block, sending notifications for cascading deletes/link nullifications +void RLMTrackDeletions(RLMRealm *realm, dispatch_block_t block); + +std::vector RLMGetObservedRows(RLMSchemaInfo const& schema); +void RLMWillChange(std::vector const& observed, std::vector const& invalidated); +void RLMDidChange(std::vector const& observed, std::vector const& invalidated);