I am trying to DRY up my app by creating a Firebase DataService but I don't know what type to cast for Auth.auth(). I looked at the Source Code Definition but it is in Objective C which I do not understand. Is extracting Auth.auth() even possible?
Here is what I have:
let FB_AUTH = Auth.auth()
let DB_BASE = Database.database().reference()
let FB_STORAGE = Storage.storage().reference()
class FBData {
static let fbi = FBData()
//MARK: PROPERTIES
private var _FB_AUTH = FB_AUTH
private var _REF_BASE = DB_BASE
private var _STORAGE_BASE = FB_STORAGE
private var _REF_USERS = DB_BASE.child("users")
//MARK: PRIVATE GETTERS
var FB_AUTH: NSObject {
return _FB_AUTH
}
var REF_BASE: DatabaseReference {
return _REF_BASE
}
var STORAGE_BASE: StorageReference
{
return _STORAGE_BASE
}
var REF_USERS: DatabaseReference {
return _REF_USERS
}
}
Looking in the source, as you said, I see:
+ (FIRAuth *)auth NS_SWIFT_NAME(auth());
(FIRAuth *) is the return type. So Auth.auth() is of type FIRAuth (Auth in Swift) which inherits from NSObject
NS_SWIFT_NAME(Auth)
#interface FIRAuth : NSObject
Related
I was wondering if there is a way to do this in a better way with generics. I have this singleton which needs a setter and another getter for every object. Plus, I have to check that the property is not nil in every getter, which is a lot of repeated code. ex:
class DataManager : NSObject {
private override init(){}
private var postData : [PostModel]?
private var userData : [UserModel]?
private var commentsData : [CommentsModel]?
private var photosData : [PhotosModel]?
private var albumsData : [AlbumsModel]?
private var todosData : [TodosModel]?
static let shared = DataManager()
//MARK : Setters
func setUserData(data : [UserModel]) {
self.userData = data
}
func setPostData(data : [PostModel]) {
self.postData = data
}
func setCommentsData(data : [CommentsModel]) {
self.commentsData = data
}
func setAlbumsData(data : [AlbumsModel]) {
self.albumsData = data
}
func setPhotosData(data : [PhotosModel]) {
self.photosData = data
}
func setTodosData(data : [TodosModel]) {
self.todosData = data
}
//MARK : Getters
func getUserData() -> [UserModel]? {
if self.userData != nil {
return self.userData!
}
return nil
}
func getPostData() -> [PostModel]? {
if self.postData != nil {
return self.postData!
}
return nil
}
func getCommentsData() -> [CommentsModel]? {
if self.commentsData != nil {
return self.commentsData!
}
return nil
}
func getAlbumsData() -> [AlbumsModel]? {
if self.albumsData != nil {
return self.albumsData!
}
return nil
}
func getPhotosData() -> [PhotosModel]? {
if self.photosData != nil {
return self.photosData!
}
return nil
}
func getTodosData() -> [TodosModel]? {
if self.todosData != nil {
return self.todosData!
}
return nil
}
}
I was wondering if all this logic could be done in one single method, maybe using generics?
If you want to force all object to set as a none optional and also get as a none optional, you don't need to define them as optional at the first place:
So instead of:
private var postData : [PostModel]?
you should have:
private var postData = [PostModel]()
This will gives you an empty none optional array and it can not be set or get as an optional.
If you want them to be nil before someone get them (for memory management or etc.), You can make them lazy:
private lazy var postData = [PostModel]()
So now postData will be nil until someone tries to read the value of it.
If you need to do some extra job when someone tries to set one of these, you can observe for changes before set and after set of the value:
private var postData = [PostModel]() {
willSet { /* right before the value is going to set */ }
didSet { /* right after the value is set */ }
}
Note that lazy properties can not have observers
So seems like you don't have any of the functions at all. And you can refactor your code to something like this:
class DataManager : NSObject {
private override init(){}
lazy var postData = [PostModel]()
lazy var userData = [UserModel]()
lazy var commentsData = [CommentsModel]()
lazy var photosData = [PhotosModel]()
lazy var albumsData = [AlbumsModel]()
lazy var todosData = [TodosModel]()
}
I keep getting this error and I failed to debug:
Could not cast value of type 'FIRDatabaseQuery' (0x10b32b700) to 'FIRDatabaseReference' (0x10b32b520).
That error comes from a regular .swift file with:
import Foundation
import Firebase
import FirebaseDatabase
let DB_BASE = FIRDatabase.database().reference()
class DataService {
static let ds = DataService()
private var _REF_BASE = DB_BASE
private var _REF_INCOMES = DB_BASE.child("incomes").queryOrdered(byChild: "date")
private var _REF_USERS = DB_BASE.child("users")
var REF_BASE: FIRDatabaseReference {
return _REF_BASE
}
var REF_INCOMES: FIRDatabaseReference {
return _REF_INCOMES as! FIRDatabaseReference // Thread 1: signal SIGABRT
}
[...]
}
Before adding .queryOrdered(byChild: "date") and as! FIRDatabaseReference everything worked except that I could not get a sort by date.
class IncomeFeedVC: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
var incomes = [Income]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
DataService.ds.REF_INCOMES.observe(.value, with: { (snapshot) in
if let snapshot = snapshot.children.allObjects as? [FIRDataSnapshot] {
for snap in snapshot {
if let incomeDict = snap.value as? Dictionary<String, AnyObject> {
let key = snap.key
let income = Income(incomeId: key, incomeData: incomeDict)
self.incomes.append(income)
}
}
}
self.tableView.reloadData()
})
}
[...]
}
What am I after? To start, I need to sort my date then work towards my Sketch view:
How do you sort? Few tutorials I see uses CoreData. Im using Firebase.
your private var _REF_INCOMES is FIRDatabaseQuery not FIRDatabaseReference ..
var REF_INCOMES: FIRDatabaseQuery {
return _REF_INCOMES
}
And please check this Q&A to sort your array
I am following this example to implement clean architecture in my iOS app.
class CreateOrderConfigurator
{
private static var __once: () = {
//ERROR - use of unresolved identifier 'Static'
Static.instance = CreateOrderConfigurator()
}()
// MARK: Object lifecycle
class var sharedInstance: CreateOrderConfigurator
{
struct Static {
static var instance: CreateOrderConfigurator?
static var token: Int = 0
}
_ = CreateOrderConfigurator.__once
return Static.instance!
}
// MARK: Configuration
func configure(_ viewController: CreateOrderViewController)
{
let router = CreateOrderRouter()
router.viewController = viewController
let presenter = CreateOrderPresenter()
presenter.output = viewController
let interactor = CreateOrderInteractor()
interactor.output = presenter
viewController.output = interactor
viewController.router = router
}
}
I get an error saying use of unresolved identifier 'Static'. How do I solve this?
PS : I am new to iOS and Swift 3.
A singleton is very simple in Swift
Replace
private static var __once: () = {
//ERROR - use of unresolved identifier 'Static'
Static.instance = CreateOrderConfigurator()
}()
// MARK: Object lifecycle
class var sharedInstance: CreateOrderConfigurator
{
struct Static {
static var instance: CreateOrderConfigurator?
static var token: Int = 0
}
_ = CreateOrderConfigurator.__once
return Static.instance!
}
with
static let sharedInstance = CreateOrderConfigurator()
class ShareData {
class var sharedInstance: ShareData {
struct Static {
static var instance: ShareData?
static var token: dispatch_once_t = 0
}
dispatch_once(&Static.token) {
Static.instance = ShareData()
}
return Static.instance!
}
var someString : String! //Some String
var selectedTheme : AnyObject! //Some Object
var someBoolValue : Bool!
}
This is my singleton design.However , I want to know how I can clear all its data as and when required?
Also can i have more than one singleton Class??
Since you've only got 3 properties on your singleton it would be far easier just to set up a method that nils each property in turn.
Once you start getting in to how to destroy and recreate your singleton, you get in to the realm of do you actually even want a singleton or should you just be using a regular object.
You are creating a Singleton with the syntax available in... 2014
Today there's a better syntax to define a Singleton class
final class SharedData {
static let sharedInstance = SharedData()
private init() { }
var someString: String?
var selectedTheme: AnyObject?
var someBoolValue: Bool?
func clear() {
someString = nil
selectedTheme = nil
someBoolValue = nil
}
}
As you can see I also added the clearData() method you were looking for.
I'm working on my first Swift based project (xcode 6.3.2) and don't seem to get a simple generics construct to build.
The following seems to fail to compile on xcode 6.3.2 (compiler exit with code 1):
// with :AnyObject constraint => compiler crash
class GenericsTest : MyDelegate{
static let instance = GenericsTest()
private init(){
var wrapper = MyWrapper<MyDelegate>(inner: self)
if let md = wrapper.inner {
println("delegate value \(md.someString)")
}
}
// MyDelegate impl
var someString = "my delegate impl"
}
protocol MyDelegate : class {
var someString : String {get set}
}
class MyWrapper<T: AnyObject>{
private (set) var inner : T?
init(inner : T){
self.inner = inner
}
}
It looks like the Swift compiler does not like the :AnyObject type constraint of MyWrapper; the following code compiles and runs without any problem:
// no :AnyObject constraint
class GenericsTest : MyDelegate{
static let instance = GenericsTest()
private init(){
var wrapper = MyWrapper<MyDelegate>(inner: self)
if let md = wrapper.inner {
println("delegate value \(md.someString)")
}
}
// MyDelegate impl
var someString = "my delegate impl"
}
protocol MyDelegate : class {
var someString : String {get set}
}
class MyWrapper<T>{
private (set) var inner : T?
init(inner : T){
self.inner = inner
}
}
I need the :AnyObject type constraint because I'm actually trying to create a weak wrapper, which requires this constraint, like so:
// with weak wrapper and obligatory :AnyObject constraint (compiler crash)
class GenericsTest : MyDelegate{
static let instance = GenericsTest()
private init(){
var wrapper = MyWrapper<MyDelegate>(inner: self)
if let md = wrapper.inner {
println("delegate value : \(md.someString)")
}
}
// MyDelegate impl
var someString = "my delegate impl"
}
protocol MyDelegate : class {
var someString : String {get set}
}
class MyWrapper<T: AnyObject>{
weak private (set) var inner : T?
init(inner : T){
self.inner = inner
}
}
Anybody any idea how to work around this issue?