Unable to create Singleton - swift

i want to make contact book to i made a class of contact.
there is no compile error but when i run the init i do not get to the "init"pass stage.
what can be the problem ?
here is my code:
import UIKit
public class contact {
var originalNumber: String = ""
var e164Number: String = ""
var contactImage: String = ""
var name: String = ""
init (originalNumber: String, name: String) {
self.originalNumber = originalNumber
self.name = name
}
}
then in my contactDataClass i made:
import UIKit
import AddressBook // imports the framework
class contactsDataClass {
var adbk : ABAddressBook!
var localContacts = [contact]()
init() {
print("get to init")
contactsDataClass.sharedInstance.localContacts.append(contact(originalNumber: "0525222022", name: "try appent"))
print("init pass")
}
struct Static {
static var onceToken : dispatch_once_t = 0
static var instance : contactsDataClass? = nil
}
class var sharedInstance : contactsDataClass {
dispatch_once(&Static.onceToken){
Static.instance = contactsDataClass()
}
return Static.instance!
}
}

You have created infinite recursion
Infact this block
class var sharedInstance : contactsDataClass {
dispatch_once(&Static.onceToken){
Static.instance = contactsDataClass()
}
return Static.instance!
}
calls this
init() {
print("get to init")
contactsDataClass.sharedInstance.localContacts.append(contact(originalNumber: "0525222022", name: "try appent"))
print("init pass")
}
which again calls the first block...
Let's clean up your code
public class Contact {
var originalNumber: String
var e164Number = ""
var contactImage = ""
var name: String
init (originalNumber: String, name: String) {
self.originalNumber = originalNumber
self.name = name
}
}
class ContactManager {
static let sharedInstance = ContactManager()
private init() {}
var adbk : ABAddressBook! // this is dangerous...
var contacts = [Contact]()
}
As you can see defining a Singleton class in Swift is much easier than in Objective-C.
You just need to hide the default initializer and create the static constant sharedInstance as shown above.
Usage
ContactManager.sharedInstance.contacts.append(Contact(originalNumber: "0525222022", name: "Test name"))
print(ContactManager.sharedInstance.contacts[0].name) // "Test name"

Related

Realm Append managed object to unmanaged object

I want to append managed object to unmanaged object in realm.
Here is the codes
class Schedule3: Object, ObjectKeyIdentifiable {
#objc dynamic var _id: String = UUID().uuidString
#objc dynamic var _partition: String = ""
let scheduleTags = RealmSwift.List<ScheduleTag3>()
#objc dynamic var title: String = ""
override static func primaryKey() -> String? {
return "_id"
}
}
class ScheduleTag3: Object, ObjectKeyIdentifiable {
#objc dynamic var _id: String = UUID().uuidString
#objc dynamic var _partition: String = ""
#objc dynamic var name: String = ""
override static func primaryKey() -> String? {
return "_id"
}
}
When I add managed ScheduleTag3 object to unmanaged Schedule3 object and append #ObsevedResults(Schedule3.self), I get error 'Object is already managed by another Realm. Use create instead to copy it into this Realm.'
Here is the code of append,
struct SchedulePreview: View {
#ObservedResults(Schedule3.self) var schedules
#ObservedResults(ScheduleTag3.self) var tags
#EnvironmentObject var scheduleModel:ScheduleIDModel
var scheduleTitle:String
var scheduleBudget:Int
var areaTag:ScheduleTag3?
#StateRealmObject var thisSchedule = Schedule3()
var body: some View {
TabView(selection: self.$selection) {
...
.navigationBarItems (
trailing: Text("make")
.onTapGesture {
thisSchedule = scheduleModel.addSchedule(scheduleTitle: scheduleTitle, scheduleBudget: scheduleBudget, areaTag: areaTag)
let scheduleId = thisSchedule._id
let areTagId = areaTag?._id
let thisAreaTag = tags.filter("_id == %#", areTagId!).first
thisSchedule.scheduleTags.append(thisAreaTag!)
$schedules.append(thisSchedule)
}
)
}
}
class ScheduleIDModel: ObservableObject {
...
func addSchedule(scheduleTitle:String, scheduleBudget:Int, areaTag:ScheduleTag3?) -> Schedule3 {
let schedule = Schedule3()
if scheduleTitle != "" {
schedule.title = scheduleTitle
}
schedule.budget = scheduleBudget
schedule._partition = "Public"
return schedule
}
}

#ObservedObject not updating after successful network call

I've hit a brick wall in my widget extension. I'm using AlamoFire and ObjectMapper to match the networking we have in the main app. I can tell that my AlamoFire network call is getting triggered and that I'm getting results back, and in the correct, expected format. However, saving the response of that network call to a #Published var doesn't seem to be working. My view and models/structs are below:
struct WidgetEntryView: View {
var entry: ResourceCategoryEntry
#ObservedObject var viewModel = WidgetResourcesView(widgetSize: .medium)
var body: some View {
if UserDefaults.forAppGroup.object(forKey: "sessionToken") as? String == nil {
PleaseLogIn()
} else if viewModel.mediumResources.count < 1 {
ErrorScreen()
} else {
MediumResourcesView(resources: viewModel.mediumResources)
}
}
}
class WidgetResourcesView: ObservableObject {
#Published var resourceGroups: [WidgetResouceGroup] = [WidgetResouceGroup]()
var widgetSize: WidgetSize = .small
var selectedCategory: String?
init(widgetSize: WidgetSize) {
self.widgetSize = widgetSize
self.selectedCategory = UserDefaults.forAppGroup.string(forKey: ResourceCategoryEntry.userDefaultKey)
getResources()
}
func getResources() {
WidgetNetworkService.getResources(widgetSize: self.widgetSize.rawValue, selectedCategory: self.selectedCategory) { resourceGroups in
DispatchQueue.main.async {
self.resourceGroups = resourceGroups
}
} failure: { _ in
print("Error Received")
}
}
var mediumResources: [WidgetResource] {
var resources = [WidgetResource]()
if let featuredResourceGroup = resourceGroups.featuredResourceGroup {
for resource in featuredResourceGroup.resources { resources.append(resource) }
}
if let nonFeaturedResourceGroup = resourceGroups.nonFeaturedResourceGroup {
for resource in nonFeaturedResourceGroup.resources { resources.append(resource) }
}
return resources
}
}
class WidgetResouceGroup: NSObject, Mappable, Identifiable {
var id = UUID()
var widgetCategory: WidgetCategory = .featured
var resources = [WidgetResource]()
required init?(map: Map) {}
func mapping(map: Map) {
id <- map["section"]
widgetCategory <- map["section"]
resources <- map["resources"]
}
}
typealias WidgetResourceGroupCollection = [WidgetResouceGroup]
extension WidgetResourceGroupCollection {
var featuredResourceGroup: WidgetResouceGroup? {
return first(where: {$0.widgetCategory == .featured})
}
var nonFeaturedResourceGroup: WidgetResouceGroup? {
return first(where: {$0.widgetCategory != .featured})
}
}
class WidgetResource: NSObject, Mappable, Identifiable {
enum ResourceType: String {
case text = "text"
case audio = "audio"
case video = "video"
}
var id = 0
var title = ""
var imageInfo: WidgetImageInfo?
var resourceType: ResourceType = .text
required init?(map: Map) {}
func mapping(map: Map) {
id <- map["object_id"]
title <- map["title"]
imageInfo <- map["image_info"]
resourceType <- map["content_type"]
}
}
You can use the objectWillChange - Property in your observable object to specifiy when the observable object should be refreshed.
Apple Dev Doku
Example by Paul Hudson
WidgetEntryView instantiates WidgetResourcesView using the ObservedObject wrapper. This causes a new instance of WidgetResourcesView to be instantiated again on every refresh. Try switching that to StateObject, and the original object will be kept in memory between view updates. I believe this is the only change needed, but I’m away so can’t test it!

How I can access to one Struct property that implements two protocols?

Im just learning Swift 4 and I have some troubles trying to access a property of an struct that have to implement 2 protocols
here is my struct
struct FigureA {
static func load() -> Model {
return Model.make(
name: "FigureName",
status: "Painted",
image: UIImage(named: "FigureA"),
description: "Good figure")
}
}
here the protocol 1
protocol ListModel: class {
var name: String { get }
var status: String { get }
var image: UIImage? { get }
}
here the protocol 2
protocol DetailModel: ListModel {
var categoryName: String { get }
var modelDescription: String? { get }
}
And I want to get the access to the description of the Struct but I don't know how at all.
Can someone give me a bit of light.
Here is good start for you:
protocol BaseProtocol {
var id: Int { get set }
}
protocol PersonProtocol: BaseProtocol {
var firstName: String { get set }
var lastName: String { get set }
var name: String { get }
}
struct Person: PersonProtocol {
var id: Int
var firstName: String
var lastName: String
var name: String { return firstName + " " + lastName }
}
//≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//Create Struct Instance & Print properties.
let person = Person(id: 1001, firstName: "Manish", lastName: "Rathi")
print(person.id)
print(person.firstName)
print(person.lastName)
print(person.name)
}
}
#HappyCoding 😊

How do you initialize a singleton with properties - Swift?

I am trying to create a singleton that gets initialized with properties.. I know you can initialize by default:
class ApiSharedHelper {
var someValue:String
static let sharedInstance : ApiSharedHelper = {
let instance = ApiSharedHelper()
return instance
}()
ApiSharedHelper.sharedInstance...
And I would just call that sharedInstance and it'll call the constructor. How would I call that shared instance where I'm passing a value for that someValue string to initialize a value?
class APIManager {
class var shared :APIManager {
struct Singleton {
static let instance = APIManager()
}
return Singleton.instance
}
func login(username: String, password: String, success:#escaping (LoginModel?)->()) { ... }
You can call it by :
APIManager.shared.login(username: txtUsername.text ?? "", password: txtPassword.text ?? "") { (response) in
print(response ?? "")
}
you can try this
class ApiSharedHelper {
var someValue:String
static let sharedInstance = ApiSharedHelper()
private init(){
}
}
ApiSharedHelper.sharedInstance...

How to create my game architecture in a protocol oriented way?

I haven't found any good ways to design a protocol oriented item architecture for games.
Heres the first version with Structs:
protocol Usable {
func useItem()
}
protocol Item {
var name: String { get }
var amount: Int { get }
var image: String { get }
}
struct Sword: Item, Usable {
var name = ""
var amount = 0
var image = ""
func useItem() {
}
}
struct Shield: Item, Usable {
var name = ""
var amount = 0
var image = ""
func useItem() {
}
}
The problem with this is I have to copy paste the variables which are A LOT of code across items.
Heres the second version with Classes:
protocol Usable {
func useItem()
}
class BaseItem {
var name = ""
var amount = 0
var image = ""
}
class SwordClass: BaseItem, Usable {
func useItem() {
}
}
This looks pretty good, but the problem is these are reference types and I would prefer them to be value types.
What is the right way to solve this problem?
You should create a generic struct which conforms to your protocols and which requires initialisation with default values and a 'use' closure:
protocol Usable {
func useItem()
}
protocol Item {
var name: String { get }
var amount: Int { get }
var image: String { get }
}
struct UsableItem: Item, Usable {
var name = ""
var amount = 0
var image = ""
let use: (Void -> Void)
init(name: String, image: String, use: (Void -> Void)) {
self.name = name
self.image = image
self.use = use
}
func useItem() {
self.use()
}
}
Then your JSON processing would create instances with the appropriate logic:
var sword = UsableItem(name: "sword", image: "sword") {
print("cut")
}