By convention, each Cocoa and Core Foundation object listed in Table
2-1 is called a property-list object.
So, does this protocol (known as PropertyListObject in the code below) exist, or do we need to make our own? If we do need to make our own, has someone made a definitive one?
public protocol UserDefaults_Value_WrappedValue {
associatedtype PropertyListObject: HM.PropertyListObject
init?(propertyListObject: Any)
var convertertedToPropertyListObject: PropertyListObject { get }
}
public protocol PropertyListObject: UserDefaults_Value_WrappedValue
where PropertyListObject == Self { }
public extension PropertyListObject {
init?(propertyListObject: Any) {
guard let object = propertyListObject as? Self
else { return nil }
self = object
}
var convertertedToPropertyListObject: Self { self }
}
extension Bool: PropertyListObject { }
extension Data: PropertyListObject { }
extension Date: PropertyListObject { }
extension String: PropertyListObject { }
extension URL: PropertyListObject { }
extension Int: PropertyListObject { }
extension Int8: PropertyListObject { }
extension Int16: PropertyListObject { }
extension Int32: PropertyListObject { }
extension Int64: PropertyListObject { }
extension UInt: PropertyListObject { }
extension UInt8: PropertyListObject { }
extension UInt16: PropertyListObject { }
extension UInt32: PropertyListObject { }
extension UInt64: PropertyListObject { }
extension Float: PropertyListObject { }
extension Double: PropertyListObject { }
extension Array: PropertyListObject & UserDefaults_Value_WrappedValue
where Element: HM.PropertyListObject {
public typealias PropertyListObject = Self
}
extension Dictionary: UserDefaults_Value_WrappedValue
where Key: LosslessStringConvertible, Value: HM.PropertyListObject {
public typealias PropertyListObject = PropertyListDictionary<Value>
public init?(propertyListObject: Any) {
guard let dictionary = propertyListObject as? PropertyListObject
else { return nil }
self.init(dictionary)
}
public var convertertedToPropertyListObject: PropertyListObject {
.init(self)
}
}
extension Dictionary: PropertyListObject
where Key == String, Value: HM.PropertyListObject { }
public typealias PropertyListDictionary<Value: PropertyListObject> = [String: Value]
import CoreGraphics
extension CGPoint: PropertyListObject { }
extension CGVector: PropertyListObject { }
extension CGSize: PropertyListObject { }
extension CGRect: PropertyListObject { }
extension CGAffineTransform: PropertyListObject { }
Use case:
The value parameter can be only property list objects: NSData,
NSString, NSNumber, NSDate, NSArray, or NSDictionary. For NSArray and
NSDictionary objects, their contents must be property list objects.
final class UserDefaultsTestCase: XCTestCase {
func test_subscript() {
let key = "🔑"
UserDefaults[key] = true
XCTAssert(UserDefaults[key] == true)
UserDefaults[key] = 9
XCTAssertEqual(UserDefaults[key], 9)
}
func test_Dictionary() {
let key = "🔑"
UserDefaults[key] = Day.ta
XCTAssertEqual(UserDefaults["🔑"], Day.ta)
UserDefaults[key] = [1: "🌞", 2: "🌛"]
XCTAssertEqual(UserDefaults["🔑"], Day.ta)
UserDefaults.standard[key] = ["1": "🌞", "2": "🌛"]
XCTAssertEqual(UserDefaults["🔑"], Day.ta)
}
func test_propertyWrapper() {
struct Type {
#UserDefaults.Value(key: "🗝") var dayta = Day.ta
}
var instance = Type()
XCTAssertEqual(instance.dayta, Day.ta)
instance.dayta = nil
XCTAssertNil(instance.dayta)
}
}
private enum Day: Int, LosslessStringConvertible {
case sunday = 1, monday
static let ta = [Day.sunday: "🌞", .monday: "🌛"]
}
public extension UserDefaults {
#propertyWrapper struct Value<WrappedValue: UserDefaults_Value_WrappedValue> {
public init(
wrappedValue: WrappedValue?,
key: String,
defaults: UserDefaults = .standard
) {
self.key = key
self.defaults = defaults
self.wrappedValue = wrappedValue
}
public var wrappedValue: WrappedValue? {
get { defaults[key] }
set { defaults[key] = newValue }
}
public let key: String
private let defaults: UserDefaults
}
static subscript<Object: UserDefaults_Value_WrappedValue>(key: String) -> Object? {
get { standard[key] }
set { standard[key] = newValue }
}
subscript<Object: UserDefaults_Value_WrappedValue>(key: String) -> Object? {
get { object(forKey: key).flatMap(Object.init) }
set { set(newValue?.convertertedToPropertyListObject, forKey: key) }
}
}
More reading: https://github.com/apple/swift-evolution/blob/master/proposals/0139-bridge-nsnumber-and-nsvalue.md
Related
protocol Base {
associatedtype M
var data:M { get set }
func update(data:M)
}
class ViewA : Base {
var data: String = ""
func update(data: String) {}
}
class ViewB : Base {
var data: Int = 2
func update(data: Int) {}
}
var dataArr : [Any] = ["1",2]
var viewArr : [Any] = [ViewA(), ViewB()]
func updatData() {
func update<C, T>(view:C, data:T) where C : Base, C.M == T {
view.update(data: data)
}
for i in 0..<2 {
let view = viewArr[i]
let data = dataArr[I]
// ! there is a errr here, Protocol 'Any' as a type cannot conform to 'Base'
update(view: view, data: data)
}
}
My Views conform to this 'Base' protocol which define what type of data my view use
And I want to implement this updatData function dynamic tell if data can be send to view (base on viwe.m type is same to data's type)
But it is seems to be impossible in Swift?
Array of Any object pass as Base Protocol create conflict.
so add one more class for Base class of ViewA and ViewB
protocol Base {
associatedtype M
var data: M { get set }
func update(data: M)
}
class Base1: Base {
typealias M = Any
var data: Any = ""
func update(data: Any) {
print("Udate \(data)")
}
}
class ViewA: Base1 {
//typealias M = String
//var data: String = ""
override func update(data: Any) {
print("test")
}
}
class ViewB: Base1 {
//typealias M = Int
//var data: Int = 2
override func update(data: Any) {
print(data)
print("Udate")
}
}
var dataArr: [Any] = ["1", 2]
var viewArr: [Any] = [ViewA(), ViewB()]
func updatData() {
func update<C, T>(view: C, data: T) where C: Base, C.M == T {
view.update(data: data)
}
for i in 0..<2 {
let view = viewArr[i]
let data = dataArr[i]
update(view: view as! Base1, data: data)
}
}
You want to create a type erased Base concrete type here: AnyBase:
public final class AnyBase: Base {
fileprivate let _boxed: _Box<M>
public init<Concrete: Base>(_ concrete: Concrete) where Concrete.M == M {
self._boxed = _ConcreteBox(concrete)
}
// Base conformance
public var data: M { _boxed.data }
public func update(data: M) {
_boxed.update(data: data)
}
// Type erasure
fileprivate class _Box<T>: Base {
init() {
guard type(of: self) != _Box.self else { fatalError("Can't create _Box instances, create a sub class instance instead ") }
}
// Base conformance
var base: M {
get { fatalError("Must override") }
set { fatalError("Must override") }
}
func update(data: M) {
fatalError("Must override")
}
}
fileprivate final class _ConcreteBox<Concrete: Base>: _Box<Concrete.M> where M == Concrete.M {
let _concrete: Concrete
init(_ concrete: Concrete) {
self._concrete = concrete
super.init()
}
// Base conformance
override var data: {
get { _concrete.data }
set { _concrete.data = newValue }
}
override func update(data: M) {
_concrete.update(data: data)
}
}
}
Now you can store different concrete instances of Base<M> in an array by adopting the type erased AnyBase<M> instead of using Any in your arrays.
This code leads to crash somewhere later with EXC_BAD_ACCESS
SomeLoader().selectedIndex = 1
class SomeLoader {
// MARK: - Public
var selectedIndex: Int? {
get {
return dataStorage.selectedIndex
}
set {
dataStorage.selectedIndex = newValue
}
}
}
this code is not crashed:
SomeLoader().selectedIndex = 1
class SomeLoader {
// MARK: - Public
var selectedIndex: Int? {
get {
return dataStorage.selectedIndex
}
set {
dataStorage.updateSelected(index: newValue)
}
}
}
where:
struct DataStorage<T: Hashable> {
enum Keys: String {
case selectedIndex
}
private func get<U>(forKey key: String) -> U? {
guard let objectData = getData(forKey: key) else {
return nil
}
let object: U? = get(forData: objectData)
return object
}
private func get<U>(forData objectData: Data) -> U? {
return NSKeyedUnarchiver.unarchiveObject(with: objectData) as? U
}
private func save<U>(forKey key: String, object: U) {
let encodedData = NSKeyedArchiver.archivedData(withRootObject: object)
UserDefaults.standard.set(encodedData, forKey: key)
}
}
extension DataStorage {
func updateSelected(index: Int?) {
guard let index = index else {
remove(forKey: Keys.selectedIndex.rawValue)
return
}
saveSelected(index: index)
}
var selectedIndex: Int? {
get {
return get(forKey: Keys.selectedIndex.rawValue)
}
set {
guard let index = newValue else {
remove(forKey: Keys.selectedIndex.rawValue)
return
}
saveSelected(index: index)
}
}
}
Why? Is it a bug?
Screenshots with an error and a callstack. The error appears later in the other part of the code.
The code below crashes in the iOS. But works in the playground.
//: Playground - noun: a place where people can play
import UIKit
struct DataStorage<T: Hashable> {
enum Keys: String {
case selectedIndex
}
private func get<U>(forKey key: String) -> U? {
guard let objectData = getData(forKey: key) else {
return nil
}
let object: U? = get(forData: objectData)
return object
}
private func get<U>(forData objectData: Data) -> U? {
return NSKeyedUnarchiver.unarchiveObject(with: objectData) as? U
}
private func save<U>(forKey key: String, object: U) {
let encodedData = NSKeyedArchiver.archivedData(withRootObject: object)
UserDefaults.standard.set(encodedData, forKey: key)
}
private func remove(forKey key: String) {
UserDefaults.standard.removeObject(forKey: key)
}
private func saveSelected(index: Int) {
save(forKey: Keys.selectedIndex.rawValue, object: index)
}
private func getData(forKey key: String) -> Data? {
return getContent(forKey: key) as? Data
}
private func getContent(forKey key: String) -> Any? {
return UserDefaults.standard.value(forKey: key)
}
}
extension DataStorage {
func updateSelected(index: Int?) {
guard let index = index else {
remove(forKey: Keys.selectedIndex.rawValue)
return
}
saveSelected(index: index)
}
var selectedIndex: Int? {
get {
return get(forKey: Keys.selectedIndex.rawValue)
}
set {
guard let index = newValue else {
remove(forKey: Keys.selectedIndex.rawValue)
return
}
saveSelected(index: index)
}
}
}
class SomeLoader {
// MARK: - Public
var dataStorage = DataStorage<Int>()
var selectedIndex: Int? {
get {
return dataStorage.selectedIndex
}
set {
dataStorage.selectedIndex = newValue
}
}
}
let someLoader = SomeLoader()
someLoader.selectedIndex = 1
print(someLoader)
The code below works everywhere
//: Playground - noun: a place where people can play
import UIKit
struct DataStorage<T: Hashable> {
enum Keys: String {
case selectedIndex
}
private func get<U>(forKey key: String) -> U? {
guard let objectData = getData(forKey: key) else {
return nil
}
let object: U? = get(forData: objectData)
return object
}
private func get<U>(forData objectData: Data) -> U? {
return NSKeyedUnarchiver.unarchiveObject(with: objectData) as? U
}
private func save<U>(forKey key: String, object: U) {
let encodedData = NSKeyedArchiver.archivedData(withRootObject: object)
UserDefaults.standard.set(encodedData, forKey: key)
}
private func remove(forKey key: String) {
UserDefaults.standard.removeObject(forKey: key)
}
private func saveSelected(index: Int) {
save(forKey: Keys.selectedIndex.rawValue, object: index)
}
private func getData(forKey key: String) -> Data? {
return getContent(forKey: key) as? Data
}
private func getContent(forKey key: String) -> Any? {
return UserDefaults.standard.value(forKey: key)
}
}
extension DataStorage {
func updateSelected(index: Int?) {
guard let index = index else {
remove(forKey: Keys.selectedIndex.rawValue)
return
}
saveSelected(index: index)
}
var selectedIndex: Int? {
get {
return get(forKey: Keys.selectedIndex.rawValue)
}
set {
guard let index = newValue else {
remove(forKey: Keys.selectedIndex.rawValue)
return
}
saveSelected(index: index)
}
}
}
class SomeLoader {
// MARK: - Public
var dataStorage = DataStorage<Int>()
var selectedIndex: Int? {
get {
return dataStorage.selectedIndex
}
set {
dataStorage.updateSelected(index: newValue)
}
}
}
let someLoader = SomeLoader()
someLoader.selectedIndex = 1
print(someLoader)
How to Convert a model object into JSON?
I want "Answer" object.
// Answers Class
class Answers {
var cat_id: String!
var responses = [Response]()
var date: String!
var comment: String!
var time: String!
var lat: String!
var lon: String!
var address: String!
}
// Response Class
class Response {
var que_id: String!
var question: String!
var response: String!
}
Make both types conform to Codable:
class Answers: Codable {
...
}
class Response: Codable {
...
}
And then use JSONEncoder:
let answers: Answers = ...
do {
let data = try JSONEncoder().encode(answers)
// use data here
} catch {
print(error)
}
See Encoding and Decoding Custom Types.
if you are using swift4, You can use encodable and decodable protocol. I'm still working on a heterogeneous list of objects. But this should work for you. Make your class conform to ABEncodable.
protocol ABDecodable: Decodable {
static func decodeFromData(_ data: Data) -> Decodable?
}
protocol ABEncodable: Encodable {
static func encodeFromObject<T>(_ object: T) -> Data? where T: Encodable
}
extension ABDecodable {
static func decodeFromData(_ data: Data) -> Decodable? {
do {
return try JSONDecoder().decode(self, from: data)
}
catch {
print(error)
}
return nil
}
}
extension ABEncodable {
static func encodeFromObject<T>(_ object: T) -> Data? where T: Encodable {
do {
return try JSONEncoder().encode(object)
}
catch {
return nil
}
}
}
//MARK: Decode mapper class
//Send jsonString or data to decode it into an required Object
final class Decode<T: Decodable> {
private func decodeData(_ data: Data) -> T? {
if let klass = T.self as? ABDecodable.Type {
if let object = klass.decodeFromData(data) as? T {
return object
}
}
else {
do {
return try JSONDecoder().decode(T.self, from: data)
}
catch {
print(error)
}
}
return nil
}
func fromJsonString(_ json: String) -> T? {
guard let data = json.data(using: String.Encoding.utf8) else { return nil }
if let object = decodeData(data) {
return object
}
return nil
}
func fromData(_ data: Data) -> T? {
if let object = decodeData(data) {
return object
}
return nil
}
}
//MARK: Encode mapper class
//Send jsonString or data to decode it into an required Object
final class Encode<N:Encodable> {
private func encodeObject(_ object: N) -> Data? {
if let klass = N.self as? ABEncodable.Type {
if let data = klass.encodeFromObject(object) {
return data
}
}
else {
do {
return try JSONEncoder().encode(object)
}
catch {
print(error)
}
}
return nil
}
func toJsonString(_ object: N) -> String? {
if let data = encodeObject(object) {
return String(data: data, encoding: .utf8)
}
return nil
}
func toData(_ object: N) -> Data? {
if let data = encodeObject(object) {
return data
}
return nil
}
}
What I want to achieve is to wait for all service calls to complete. I know that it can be done with GCD, but I'm looking for more Object Oriented Approach. Here is what I've so far:
First services should notify delegate for their completion, so we will need a protocol for that:
protocol ParallelServiceDelegate: class {
func serviceDidCompleted()
}
Services are Alamofire requests and we are getting their response as:
enum ServiceResult {
case Success(NSDictionary)
case Failure(NSError)
}
My design is to add Facade (wrapper) over this methods. This is the abstract:
import ObjectMapper
protocol ParallelService: class {
associatedtype ItemType: Mappable
var item: ItemType? { get }
var error: NSError? { get }
var isCompleted: Bool { get }
weak var delegate: ParallelServiceDelegate? { get set }
// TODO: Pass params
func start()
func handleRequestCompletion(result: ServiceResult)
}
private var psiAssociationKey: UInt8 = 0
private var pseAssociationKey: UInt8 = 0
private var psdAssociationKey: UInt8 = 0
extension ParallelService {
var item: ItemType? {
return _item
}
var error: NSError? {
return _error
}
var isCompleted: Bool {
return item != nil || error != nil
}
weak var delegate: ParallelServiceDelegate? {
get {
let object = objc_getAssociatedObject(self, &psdAssociationKey)
let wrapper = object as? WeakWrapper<ItemType?>
return wrapper?.value as? ParallelServiceDelegate
}
set(newValue) {
objc_setAssociatedObject(self,
&psdAssociationKey,
WeakWrapper(value: newValue),
.OBJC_ASSOCIATION_RETAIN)
}
}
func handleRequestCompletion(result: ServiceResult) {
switch result {
case .Success(let json):
_item = map(json, object: ItemType.self)
case .Failure(let error):
_error = error
}
}
// Degfault is nothing
func start() {}
// MARK: - Private
private var _item: ItemType? {
get {
let object = objc_getAssociatedObject(self, &psiAssociationKey)
let wrapper = object as? WeakWrapper<ItemType?>
return wrapper?.value as? ItemType
}
set(newValue) {
objc_setAssociatedObject(self,
&psiAssociationKey,
WeakWrapper(value: newValue),
.OBJC_ASSOCIATION_RETAIN)
}
}
private var _error: NSError? {
get {
let object = objc_getAssociatedObject(self, &pseAssociationKey)
return object as? NSError
}
set(newValue) {
objc_setAssociatedObject(self,
&pseAssociationKey,
newValue,
.OBJC_ASSOCIATION_RETAIN)
}
}
}
And Specific Service Facade implementation:
class EmployeesParallelService: ParallelService {
typealias ItemType = Employee
func start() {
Service.emploeesList(callback: handleRequestCompletion)
}
}
class InformationParallelService: ParallelService {
typealias ItemType = Information
func start() {
Service.information(callback: handleRequestCompletion)
}
}
Service caller - Knows nothing about services it just starts all and waits for them to complete:
class ParallelServiceCaller {
private var services: [ParallelService] = []
// MARK: - Lifecycle
func addParallelService(service: ParallelService) {
service.delegate = self
self.services.append(service)
}
// MARK: - Public
func start() {
for service in services {
service.start()
}
}
}
extension ParallelServiceCaller: ParallelServiceDelegate {
func serviceDidCompleted() {
for service in services {
// !!! wait
if !service.isCompleted {
return
}
}
// TODO: Notify delegate
}
}
Latter I want to use it like this:
let caller = ParallelServiceCaller()
caller.addParallelService(EmployeesParallelService())
caller.addParallelService(InformationParallelService())
caller.start()
However I got problem in the implementation of the ParallelServiceCaller class. I'm getting the following error:
Protocol 'ParallelService' can only be used as a generic constraint
because it has Self or associated type requirements
Any idea how to avoid this error?
Update 07/07/16:
I'm still not able to understand how to use PATs. However I took slightly different approach and now I'm using visitor pattern. Here is my playground code, it may be helpful for someone:
//: Playground - noun: a place where people can play
import UIKit
// Mocks
enum ServiceResult {
case Success(NSDictionary)
case Failure(NSError)
}
protocol Mappable { }
typealias CompletionHandlerType = (result: ServiceResult) -> Void
class Service {
class func emploeesList(start: Int? = nil,
max: Int? = nil,
timestamp: Int? = nil,
callback: CompletionHandlerType) {
callback(result: .Success(NSDictionary()))
}
class func information(timestamp: Int? = nil,
callback: CompletionHandlerType) {
callback(result: .Failure(NSError(domain: "", code: 1, userInfo: nil)))
}
}
class EmployeesList: Mappable {}
class Information: Mappable {}
// Actual Implementation
// Visitor
protocol ParallelServiceCallerProtocol {
func call(service: EmployeesListParallelService)
func call(service: InformationParallelService)
}
// Element
protocol ParallelServiceProtocol {
func start(visitor: ParallelServiceCallerProtocol)
}
// Concrete Elements
class EmployeesListParallelService: ParallelServiceProtocol {
func start(visitor: ParallelServiceCallerProtocol) { visitor.call(self) }
}
class InformationParallelService: ParallelServiceProtocol {
func start(visitor: ParallelServiceCallerProtocol) { visitor.call(self) }
}
// Concrete Visitor Delegate - defines callback for async tasks
protocol ParallelServiceCallerDelegateProtocol: class {
func didCompleteParellelServiceWithResult(service: ParallelServiceProtocol, result: ServiceResult)
}
// Concrete Visitor - make API calls
class ParallelServiceCaller <T: ParallelServiceCallerDelegateProtocol>: ParallelServiceCallerProtocol {
private unowned let delegate: T
init(delegate: T) {
self.delegate = delegate
}
func call(service: EmployeesListParallelService) {
Service.emploeesList { [unowned self] (result) in
self.delegate.didCompleteParellelServiceWithResult(service, result: result)
}
}
func call(service: InformationParallelService) {
Service.information { (result) in
self.delegate.didCompleteParellelServiceWithResult(service, result: result)
}
}
}
// Service Result In Context
enum SynchronizationServiceResult {
case Employees(ServiceResult)
case Information(ServiceResult)
}
// Concrete Visitor - Wraps API Result And Gives Context
class ParallelServiceParser: ParallelServiceCallerProtocol {
var result: SynchronizationServiceResult?
private let serviceResult: ServiceResult
init(serviceResult: ServiceResult) {
self.serviceResult = serviceResult
}
func call(service: EmployeesListParallelService) {
result = .Employees(serviceResult)
}
func call(service: InformationParallelService) {
result = .Information(serviceResult)
}
}
// Delegate that notifies for completion of all calls
protocol ParallelServiceManagerDelegateProtocol: class {
func didCompleteAllServicesWithResults(results: [SynchronizationServiceResult])
}
// Manager - starts all calls and adds context to returned results - knows nothing about calls
class ParallelServiceManager<T where T: ParallelServiceManagerDelegateProtocol> {
private let services: [ParallelServiceProtocol]
private unowned let delegate: T
// Keep Caller Visitors in Memory or they will be dealocated
private var callers: [ParallelServiceCaller<ParallelServiceManager>] = []
private var completed: [SynchronizationServiceResult] = [] {
didSet {
if completed.count == services.count {
self.delegate.didCompleteAllServicesWithResults(completed)
self.callers.removeAll()
}
}
}
init(services: [ParallelServiceProtocol], delegate: T) {
self.services = services
self.delegate = delegate
}
func start() {
visitAllServices { (service) in
let caller =
ParallelServiceCaller<ParallelServiceManager>(delegate: self)
service.start(caller)
self.callers.append(caller)
}
}
private func visitAllServices(perform: ParallelServiceProtocol -> () ) {
for service in self.services {
perform(service)
}
}
}
extension ParallelServiceManager: ParallelServiceCallerDelegateProtocol {
func didCompleteParellelServiceWithResult(service: ParallelServiceProtocol,
result: ServiceResult) {
// No need to persist parser visitor
let caller = ParallelServiceParser(serviceResult: result)
service.start(caller)
completed.append(caller.result!)
}
}
// Example Usage
class SynchronizationService {
private lazy var services: [ParallelServiceProtocol] = {
return [EmployeesListParallelService(), InformationParallelService()]
}()
func start() {
let manager = ParallelServiceManager<SynchronizationService>(services: services, delegate: self)
manager.start()
}
}
extension SynchronizationService: ParallelServiceManagerDelegateProtocol {
func didCompleteAllServicesWithResults(results: [SynchronizationServiceResult]) {
for result in results {
switch result {
case .Employees(let result):
// TODO:
print("\(result)") // Should Return Success
case .Information(let result):
// TODO:
print("\(result)") // Should Return Failure
}
}
}
}
let sync = SynchronizationService()
sync.start()
If anyone has any experience working with Parse using Swift, specifically subclassing PFObject..... I cannot figure out why the saveinbackground call below is throwing the above error?
Thanks!
func saveNewPerson(name: String) {
var myPeeps = [Person]()
if let currentUser = PFUser.currentUser() {
if currentUser.valueForKey("myPeeps")?.count < 1 {
myPeeps = []
} else {
myPeeps = currentUser.valueForKey("myPeeps") as! [Person]
}
let newPerson = Person(name: name, stores: [:])
myPeeps.append(newPerson)
currentUser.setObject(myPeeps, forKey: "myPeeps")
println(currentUser.valueForKey("myPeeps")?.count)
//WHY DOES THIS SAVE THROW ERROR FOR NOT INITIALZING?
currentUser.saveInBackgroundWithBlock{ succeeded, error in
if succeeded {
//3
println("Saved")
} else {
//4
if let errorMessage = error?.userInfo?["error"] as? String {
self.showErrorView(error!)
}
}
}
}
}
This is my Person class:
class Person: PFObject, PFSubclassing {
override class func initialize() {
struct Static {
static var onceToken : dispatch_once_t = 0;
}
dispatch_once(&Static.onceToken) {
self.registerSubclass()
}
}
static func parseClassName() -> String {
return "Person"
}
var name: String = ""
var stores: [String : Store] = [:]
init(name: String, stores: [String : Store]) {
self.name = name
self.stores = stores
super.init()
}
}
My Store Class:
class Store: PFObject, PFSubclassing {
override class func initialize() {
struct Static {
static var onceToken : dispatch_once_t = 0;
}
dispatch_once(&Static.onceToken) {
self.registerSubclass()
}
}
static func parseClassName() -> String {
return "Store"
}
var name: String = ""
var clothingSizes: [String: String] = [:]
init(name: String, clothingSizes: [String: String]){
self.name = name
self.clothingSizes = clothingSizes
super.init()
}
}
For both Parse subclasses, you need to make your inits convenience inits. Basically, what's going on is there is no implementation of init(), which you could do, by calling
override init() {
super.init()
}
Another option is to make your init a convenience init, and calling self.init()
convenience init(name: String, stores: [String : Store]) {
self.init()
self.name = name
self.stores = stores
}