My iOS app is returning this error.
EXC_BAD_ACCESS(code=EXC_i386_GPFLT )
This is occuring on return Singleton.instance Here is the code regarding the singleton I am using.
class var sharedData : SharedData {
struct Singleton {
static let instance = SharedData()
}
return Singleton.instance
}
Can someone help me understand this error and help me resolve it? Any suggestions or tips are appreciated it.
With Swift 1.2 there is an easier option to create singletons now:
class DataManager {
static let sharedInstance = DataManager()
/// To deny direct access, make your init function private if you want
private init() {
}
}
I was using a singleton as others have mentioned above,
static let sharedData = SharedData()
and it was crashing on a real device but not in the simulator. It turns out that I just needed to clean the project and rebuild.
Don't fall for false positives ;)
You can replace all your code with the following:
static let sharedData = SharedData()
I had a badly named function in my Swift singleton class, that must have been tripping up ARC when it was called. This class initializes another class from a file, and so I ended up with this signature:
func initOtherClass(otherClass: NSObject, URL fileURL: NSURL) -> Bool
Whoops. Changing the name from init to initialize solved the EXC_BAD_ACCESS errors. I hope this helps to save someone else some time.
Related
How do you (if possible) create a class that anything that references it gets the same object?
So, if I had a LoginClass
and I dont want to create a new instance in each file but rather be able to just do
LoginClass.userID
in any file without first creating an instance of it?
It possible. Use singleton:
Stackoverflow question
Tutorial by Ray Wenderlich
You are looking for a Singleton
This is the code
class Login {
static let sharedInstance = Login()
var userID: String?
private init() {}
}
This is how you retrieve the same instance
Login.sharedInstance
And this is how you use it
Login.sharedInstance.userID = "123"
In a different point of your code...
print(Login.sharedInstance.userID) // 123
Creating one instance per application life cycle means you want to implement Singleton pattern. You can implement singleton like this
class LoginManager {
static let sharedInstance = LoginManager()
var userId:String?
var name:String?
}
And now you can use this like
LoginManager.sharedInstance.userId
I have a framework where I have a singleton class, let's say Singleton. This class is used by other classes in the framework.
In the app project I want to subclass this singleton class, e.g. AppSingleton: Singleton. Is it possible? What is the right solution?
I provide a solution but it may be a little hacky.
Class A {
open class var shared: A {
return A.privateShared
}
private static let privateShared = A()
}
Class B {
open class var shared: B {
return A.privateShared
}
private static let privateShared = B()
}
I must clarify, this ways isn't perfect since it actually create 2 instance! So, it will technically not a singleton any more.
However, you can override the class B's property or method to call A.shared method or property instead. You must know what you are doing and consider use the other way to fix the problem you want to solve.
So I've got a subclass of an NSObject in which I implemented this:
struct SharedStruct {
static var sharedInstance = TaskCoordinator()
}
class var sharedInstance:TaskCoordinator {
get { return SharedStruct.sharedInstance }
set { SharedStruct.sharedInstance = newValue }
}
When I call this anywhere, the App hangs without an error. Is this a known issue or am I doing something wrong here?
Maybe some kind of loop, did you halt the execution and look at the stack?
I want to define a static variable on a class using Swift 2 that is a NSLock.
After researching I discovered that I have to use a struct, in something like this:
class Entity: NSManagedObject {
struct Mechanism {
static let lock = NSLock()
}
func myFunction -> NSArray {
Mechanism.lock.lock()
// do something
Mechanism.lock.unlock()
}
}
Will this work like C? I mean, the first time Mechanism is used a static lock constant will be created and subsequent calls will use the same constant?
I feel that this is not correct because the line
static let lock = NSLock()
is initializing a NSLock. So it will initialize a new one every time.
If this was not swift I would do like this:
static NSLock *lock;
if (!lock) {
lock = ... initialize
}
How do I do the equivalent in Swift 2?
You said that "after researching, I discovered that I have to use a struct [to get a static]." You then go on to ask whether it really is a static a how it changes in Swift 2.0.
So, a couple of observations:
Yes, this static within a struct pattern will achieve the desired behavior, that only one NSLock will be instantiated.
The significant change in the language was in Swift 1.2 (not 2.0), which now allows static variables, eliminating the need for the struct altogether:
class Entity: NSManagedObject {
static let lock = NSLock()
func myFunction() -> NSArray {
Entity.lock.lock()
// do something
Entity.lock.unlock()
}
}
Seriously, nobody uses NSLock on MacOS X or iOS. In Objective C, you use #synchronized. In Swift, you use a global function like this:
func Synchronized (obj: AnyObject, _ block: dispatch_block_t)
{
objc_sync_enter (obj)
block ()
objc_sync_exit (obj)
}
First, this uses a recursive lock. That alone will safe you gazillions of headaches. Second, it works much more fine grained, with a lock for one specific object. To use:
func myFunction() -> NSArray {
Synchronized(someObject) {
// Stuff to do.
}
}
I have created a project to test the Typhoon framework , I have created two classes ApplicationAssembly and CoreAssembly where I inject some properties and constructors and a default Configuration.plist to load data from it.
ApplicationAssembly
public class ApplicationAssembly: TyphoonAssembly {
public dynamic func config() -> AnyObject {
return TyphoonDefinition.configDefinitionWithName("Config.plist")
}
}
CoreAssembly
public class CoreAssembly: TyphoonAssembly {
public dynamic func apiHandler() -> AnyObject {
return TyphoonDefinition.withClass(ApiHandler.self) {
(definition) in
definition.useInitializer("initWithDebugging:debugProcess:mainURL:") {
(initializer) in
initializer.injectParameterWith(TyphoonConfig("debug_mode"))
initializer.injectParameterWith(TyphoonConfig("debug_path"))
initializer.injectParameterWith(TyphoonConfig("api_url"))
}
definition.scope = TyphoonScope.Singleton
}
}
public dynamic func viewController() -> AnyObject {
return TyphoonDefinition.withClass(ViewController.self) {
(definition) in
definition.injectProperty("apiHandler", with:self.apiHandler())
}
}
}
I set in my Info.plist the TyphoonInitialAssemblies first the ApplicationAssembly and then the CoreAssembly.
Everything works fine without exceptions or anything except that the app never enters in AppDelegate neither in the ViewController class. I don't know maybe I missed something in the doc or anything.
What I'm missing here?
Why in debug not enter in the ViewController class that is the initial view controller in Storyboard?
The problem was that the ApiHandler class does not extend NSObject, which is a requirement. This is because Typhoon is an introspective Dependency Injection container. As Swift has no native introspection it uses the Objective-C run-time.
The App should not however have crashed in such an obfuscated way. I have opened an issue to look at how to fail with a meaningful error, rather than infinitely recurse.
After solving the initial problem, I also noted that the init method for ApiHandler passing in a Swift Bool object. This needs to be an NSNumber.
init(debugging : NSNumber, debugProcess : String, mainURL : String) {
self.debugging = debugging.boolValue
self.debugProcess = debugProcess
self.mainURL = mainURL
}
Given that Typhoon uses the Objective-C runtime, there are a few quirks to using it with Swift - the same kinds of rules outlined for using Swift with KVO apply.