Realtime es el marco ORM que hace que la creación de estructuras de bases de datos complejas sea simple.
Estructura de modelo escalable simple
Archivos
Colecciones
Referencias
Ui, forma
La base de datos de Firebase real es totalmente compatible y se usa en producción. Si usa la API Clean Firebase, RealTime puede ayudar a crear la aplicación más rápido, a continuación para aplicar estructuras complejas para almacenar datos, para actualizar la interfaz de usuario utilizando comportamientos reactivos. RealTime proporciona tráfico de datos liviano, inicialización perezosa de datos, buena distribución de datos.
FoundationDB es compatible, pero con algunas limitaciones, porque FDB no tiene mecanismos de observación nativos.
En AppDelegate en func application(_:didFinishLaunchingWithOptions:) Debe llamar al código a continuación, para configurar el entorno de trabajo. Ahora, para la política de caché, es case .noCache, .persistance ,. El caché en la memoria aún no está implementado.
func application ( _ application : UIApplication , didFinishLaunchingWithOptions launchOptions : [ UIApplicationLaunchOptionsKey : Any ] ? ) -> Bool {
/// ...
/// initialize Realtime
RealtimeApp . initialize ( ... )
///...
return true
} Para crear cualquier estructura de datos modelo que pueda hacer subclasificando Object . Puede definir las propiedades infantiles utilizando clases:
Object ;ReadonlyProperty , Property , Reference , Relation , ReadonlyFile , File ;References , Values , AssociatedValues , etc. Si usa propiedades perezosas, necesita implementar la función de clase lazyPropertyKeyPath(for:) . (Por favor, dígame si sabe cómo evitarlo, sin heredar nsobject). Esta función solicitó cada subclase, por lo tanto, no necesita una super implementación de llamadas. Ejemplo: class User : Object {
lazy var name : Property < String > = " name " . property ( in : self )
lazy var age : Property < Int > = " age " . property ( in : self )
lazy var photo : File < UIImage ? > = " photo " . file ( in : self , representer : . png )
lazy var groups : References < RealtimeGroup > = " groups " . references ( in : self , elements : . groups )
lazy var scheduledConversations : Values < Conversation > = " scheduledConversations " . values ( in : self )
lazy var ownedGroup : Relation < RealtimeGroup ? > = " ownedGroup " . relation ( in : self , " manager " )
override class func lazyPropertyKeyPath ( for label : String ) -> AnyKeyPath ? {
switch label {
case " name " : return User . name
case " age " : return User . age
case " photo " : return User . photo
case " groups " : return User . groups
case " ownedGroup " : return User . ownedGroup
case " scheduledConversations " : return User . scheduledConversations
default : return nil
}
}
}
let user = User ( in : Node ( key : " user_1 " ) )
user . name <== " User name "
user . photo <== UIImage ( named : " img " )
let transaction = user . save ( in : . root )
transaction . commit ( with : { state , err in
/// process error
} )ReadonlyProperty : propiedad almacenada lectura para cualquier valor.
Propiedad : propiedad almacenada para cualquier valor.
Referencia : almacena referencia en cualquier valor de la base de datos. No implica integridad referencial. Úselo si no se eliminará el registro o de lo contrario otra razón que no necesita integridad referencial.
Relación : almacena referencia en cualquier valor de la base de datos.
ReadonlyFile : propiedad de lectura almacenada para el archivo en el almacenamiento de Firebase.
Archivo : propiedad almacenada para el archivo en Firebase Storage.
Todas las propiedades adoptan la función @propertyWrapper , pero si bien Swift no tiene acceso a self en propiedades perezosas personalizadas, esta forma de definir propiedades generalmente inútiles.
class Some : Object {
lazy var array : Values < Object > = " some_array " . values ( in : self )
lazy var references : References < Object > = " some_linked_array " . references ( in : self , elements : . linkedObjects )
lazy var dictionary : AssociatedValues < Object > = " some_dictionary " . dictionary ( in : self , keys : . keyObjects )
} Algunas operaciones mutables de colecciones pueden requerir el estado isSynced . Para lograr este estado, use la función func runObserving() o establezca la propiedad keepSynced: Bool a true .
(Distribuido) Referencias es una matriz que almacena objetos como referencias. Los elementos de origen deben ubicarse en la misma referencia. En la inserción del objeto a esta matriz crea un enlace en el objeto lateral.
Los valores (explícitos) son una matriz que almacena objetos por valor en sí mismo ubicación. El prefijo 'explícito' se utiliza en la colección que almacena elementos sin vista de colección.
References , Values mutantes:
do {
let transaction = Transaction ( )
...
let element = Element ( )
try array . write ( element : element , in : transaction )
try otherArray . remove ( at : 1 , in : trasaction )
transaction . commit { ( err ) in
// process error
self . tableView . reloadData ( )
}
} catch let e {
// process error
}(Explícito) Associated Values es un diccionario donde las claves son referencias, pero los valores son objetos. En el valor de guardado crea un enlace en el objeto de clave lateral.
AssociatedValues Mutator:
do {
let transaction = Transaction ( )
...
let element = Element ( )
try dictionary . write ( element : element , key : key , in : transaction )
try otherDictionary . remove ( by : key , in : transaction )
transaction . commit { ( err ) in
// process error
}
} catch let e {
// process error
}MapRealTimecollection es una colección inmutable que obtiene elementos de la función de mapa. Este es el resultado de X.LazyMap (_ Transform :) Método, donde X es cualquier RealTimecollection.
let userNames = Values < User > ( in : usersNode ) . lazyMap { user in
return user . name
}<== - Operador de asignación. Puede usar para asignar (o recuperar) el valor a (desde) cualquier propiedad en tiempo real.==== ,! !=== - Operadores de comparación. Puede usar para comparar cualquier propiedad en tiempo real donde sus valores se ajusten al protocolo Equatable .?? - Infix Operator, que realiza una operación nil-Coalcing, devolviendo el valor envuelto de una propiedad en tiempo real o un valor predeterminado.<- - Operador de prefijo. Puede usar para convertir la instancia de Closure, Assign tipos al cierre explícito o hacia atrás.Transacción : objeto que contiene toda la información sobre las transacciones de escritura. Casi todos los cambios de datos funcionan usando este objeto. Las operaciones más mutables simplemente toman la transacción como parámetro, pero para crear operaciones complejas personalizadas puede usar estos métodos:
/// adds operation of save RealtimeValue as single value as is
func set < T > ( _ value : T , by node : Node ) where T : RealtimeValue & RealtimeValueEvents
/// adds operation of delete RealtimeValue
func delete < T > ( _ value : T ) where T : RealtimeValue & RealtimeValueEvents
/// adds operation of update RealtimeValue
func update < T > ( _ value : T ) where T : ChangeableRealtimeValue & RealtimeValueEvents & Reverting
/// method to merge actions of other transaction
func merge ( _ other : Transaction )Para más detalles, consulte el proyecto de ejemplo.
SingleSectionTableViewDelegate : proporciona una fuente de datos de sección única para UableView con actualización automática. SectEdTableViewDelegate : proporciona una fuente de datos seccionada para UableView con Auto Update. CollectionViewDelegate : proporciona una fuente de datos para UicollectionView con actualización automática.
delegate . register ( UITableViewCell . self ) { ( item , cell , user , ip ) in
item . bind (
user . name , { cell , name in
cell . textLabel ? . text = name
} ,
{ err in
print ( err )
}
)
}
delegate . bind ( tableView )
delegate . tableDelegate = self
// data
users . changes
. listening (
onValue : { [ weak tableView ] ( e ) in
guard let tv = tableView else { return }
switch e {
case . initial : tv . reloadData ( )
case . updated ( let deleted , let inserted , let modified , let moved ) :
tv . beginUpdates ( )
tv . insertRows ( at : inserted . map ( { IndexPath ( row : $0 , section : 0 ) } ) , with : . automatic )
tv . deleteRows ( at : deleted . map ( { IndexPath ( row : $0 , section : 0 ) } ) , with : . automatic )
tv . reloadRows ( at : modified . map ( { IndexPath ( row : $0 , section : 0 ) } ) , with : . automatic )
moved . forEach { from , to in
tv . moveRow ( at : IndexPath ( row : from , section : 0 ) , to : IndexPath ( row : to , section : 0 ) )
}
tv . endUpdates ( )
}
} ,
onError : onError
)
. add ( to : listeningCollector ) Disponible como módulo separado con soporte Combine .
class User : Object {
var name : Property < String >
var age : Property < Int >
}
class FormViewController : UIViewController {
var form : Form < User >
override func viewDidLoad ( ) {
super . viewDidLoad ( )
let name = Row < TextCell , Model > . inputRow (
" input " ,
title : Localized . name ,
keyboard : . name ,
placeholder : . inputPlaceholder ( Localized . name ) ,
onText : { $0 . name <== $1 }
)
name . onUpdate { ( args , row ) in
args . view . textField . text <== args . model . name
}
let age = Row < TextCell , Model > . inputRow (
" input " ,
title : Localized . age ,
keyboard : . numberPad ,
placeholder : requiredPlaceholder ,
onText : { $0 . age <== $1 }
)
age . onUpdate { ( args , row ) in
args . view . textField . text <== args . model . age
}
let button : Row < ButtonCell , Model > = Row ( reuseIdentifier : " button " )
button . onUpdate { ( args , row ) in
args . view . titleLabel . text = Localized . login
}
button . onSelect { [ unowned self ] ( _ , row ) in
self . submit ( )
}
let fieldsSection : StaticSection < Model > = StaticSection ( headerTitle : nil , footerTitle : nil )
fieldsSection . addRow ( name )
fieldsSection . addRow ( age )
let buttonSection : StaticSection < Model > = StaticSection ( headerTitle : nil , footerTitle : nil )
buttonSection . addRow ( button )
form = Form ( model : User ( ) , sections : [ fieldsSection , buttonSection ] )
form . tableView = tableView
form . tableDelegate = self
}
}Para recibir cambios a nivel local, use objetos que conformen este protocolo. Tiene una interfaz RXSWIFT similar.
public protocol Listenable {
associatedtype OutData
/// Disposable listening of value
func listening ( _ assign : Assign < OutData > ) -> Disposable
}Agregue el argumento de depuración 'RealTime_Crash_on_error' aprobado en el lanzamiento, para captar errores internos.
También existe el módulo NodeJS, creado para la aplicación Vue.js. Código fuente que puede encontrar en la carpeta js .
Los objetos en tiempo real no deben pasar entre hilos.
Para ejecutar el proyecto de ejemplo, clonar el repositorio y ejecutar pod install desde el directorio de ejemplo.
Xcode 9+, Swift 4.1+.
Swiftpm
. package ( url : " https://github.com/k-o-d-e-n/realtime.git " , . branch ( " master " ) )RealTime está disponible a través de Cocoapods. Para instalarlo, simplemente agregue la siguiente línea a su Podfile:
pod 'Realtime' pod 'RealtimeForm/Combine' , :git => 'https://github.com/k-o-d-e-n/Realtime.git' , :branch => 'master' Koryttsev Denis, [email protected]
Twitter: @K_O_D_E_N
RealTime está disponible bajo la licencia MIT. Consulte el archivo de licencia para obtener más información.