iOS(Swift) App hangs after calling a struct's static var - ios

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?

Related

Cant typecast variable to specific child class involving Generics

Note: Sorry could not come-up with better title than this, so please
suggest a better one if you come across one after reading the question
I have a BasePresenter class, That should take BaseInteractor and BaseRouter as its init arguments, and each child class of BasePresenter should be able to specify subclass of BaseInteractor and BaseRouter in their implementation
So I have declared my BasePresenter as
open class PRBasePresenter<T: PRBaseInteractor, R: PRBaseRouter> {
var interactor: T!
var router: R!
let disposeBag = DisposeBag()
convenience init(with router : R, interactor : T) {
self.init()
self.router = router
self.interactor = interactor
}
}
So now PRBaseCollectionsPresenter which is a child of PRBasePresenter declares its interactor and router as
class PRBaseCollectionsPresenter: PRBasePresenter<PRBaseCollectionsInteractor, PRBaseCollectionRouter> {
//other code here
}
Obviously PRBaseCollectionsInteractor is a subclass of PRBaseInteractor and PRBaseCollectionRouter is a subclass of PRBaseRouter
Everything works till here fine. Now comes the issue. Every ViewController should have presenter as a property. So I have a protocol which mandates that with
protocol PresenterInjectorProtocol {
var presenter : PRBasePresenter<PRBaseInteractor, PRBaseRouter>! { get set }
}
And my BaseViewController confirms to PresenterInjectorProtocol
public class PRBaseViewController: UIViewController,PresenterInjectorProtocol {
var presenter: PRBasePresenter<PRBaseInteractor, PRBaseRouter>!
//other code...
}
Now lets say I have ChildViewController, it will obviously get presenter because of inheritance, but obviously child would want to have its specific presenter than having a generic one. And obviously in Swift when you override a property you cant change the type of the variable. So the only way is
class PRBaseTableViewController: PRBaseViewController {
var tableSpecificPresenter: PRBaseCollectionsPresenter {
get {
return self.presenter as! PRBaseCollectionsPresenter
}
}
//other code goes here
}
This gives me a warning
Cast from 'PRBasePresenter!' to
unrelated type 'PRBaseCollectionsPresenter' always fails
And trying to ignore it and running will result in crash :(
How can I solve this problem? What am I doing wrong? Or is this approach completely wrong?

Will this static var work like C?

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.
}
}

Accessing ViewController class from another class in Swift

I'm new in iOS development,
I have and "API Helper" Swift class that gets some data as a JSON array. And when the array is ready I want to call a method in my MasterViewController to update the tableView with the data.
I tried to do like that:
var facilities : [Facility]? {
didSet {
MasterViewController().facilitiesLoaded()
}
}
And then reload the tableView but without seeing anything.
I think the problem is that I'm creating a new instance of the ViewController, but what I should have is to get access to the current instance of the class.
Any idea, or a better design? Thanks..
If this "facilities" variable is instance of MasterViewController then do :
var facilities : [Facility]? {
didSet {
self.facilitiesLoaded()
}
}
Thanks to #dcestari,
I did added callback blocks to the API call and handled it in the ViewController and that did the trick
In API caller method:
func loadFacilities(completionHandler:(() -> Void!)) {
// do stuff
completionHander()
}
In the ViewController:
func getFacilities() {
api.loadFacilities({
// update tableView
})
}

iOS Swift : EXC_BAD_ACCESS(code=EXC_i386_GPFLT ) regarding a singleton

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.

What's the Swift equivalent of declaring `typedef SomeClass<SomeProtocol> MyType`?

I’m currently writing some Swift code in a project that is predominately Objective-C. In our ObjC code, we have a header that declares typedef GPUImageOutput<GPUImageInput> MyFilter;. We can then declare e.g. a #property that can only be a GPUImageOutput subclass that implements GPUImageInput.
(NOTE: GPUImageOutput and GPUImageInput are not defined by me; they are part of the GPUImage library)
Our Swift code doesn't seem to recognize this, even though the header is #imported in our Bridging Header. I’ve tried to replicate the declaration in Swift, but neither of these are proper syntax:
typealias MyFilter = GPUImageOutput, GPUImageInput
typealias MyFilter = GPUImageOutput : GPUImageInput
You can't declare typealias like that.
The best we can do is something like this:
class MyClass {
private var filter:GPUImageOutput
init<FilterType:GPUImageOutput where FilterType:GPUImageInput>(filter:FilterType) {
self.filter = filter
}
func setFilter<FilterType:GPUImageOutput where FilterType:GPUImageInput>(filter:FilterType) {
self.filter = filter
}
func someMethod() {
let output = self.filter
let input = self.filter as GPUImageInput
output.someOutputMethod()
input.someInputMethod()
}
}
In Swift 4 you can achieve this with the new & sign (Below an example of a parameter confirming to UIViewController and UITableViewDataSource:
func foo(vc: UIViewController & UITableViewDataSource) {
// access UIViewController property
let view = vc.view
// call UITableViewDataSource method
let sections = vc.numberOfSectionsInTableView?(tableView)
}
In Swift, something like the following should accomplish your task, but it's different than its ObjC counterpart:
typealias GPUImageOutput = UIImage
#objc protocol GPUImageInput {
func lotsOfInput()
}
class GPUImageOutputWithInput: GPUImageOutput, GPUImageInput
{
func lotsOfInput() {
println("lotsOfInput")
}
}
// ...
var someGpuImage = GPUImageOutput()
var specificGpuImage = GPUImageOutputWithInput()
for image in [someGpuImage, specificGpuImage] {
if let specificImage = image as? GPUImageInput {
specificImage.lotsOfInput()
} else {
println("the less specific type")
}
}
UPDATE: now that I understand where/why you have these types ...
GPUImage seems to have a swift example that does what you want, as Swift-ly as possible.
See here:
class FilterOperation<FilterClass: GPUImageOutput where FilterClass: GPUImageInput>: FilterOperationInterface {
...
The type constraint syntax can be applied to functions, too, and with a where clause, that's probably as good as you're going to get directly in Swift.
The more I tried to understand how to port this somewhat common objc trope, the more I realized it was the most Swift-way. Once I saw the example in GPUImage itself, I was convinced it was at least your answer. :-)
UPDATE 2: So, besides the specific GPUImage example I linked to above that uses Swift, the more and more I think about this, either using a where clause to guard the setter function, or using a computable property to filter the set functionality seems the only way to go.
I came up with this strategy:
import Foundation
#objc protocol SpecialProtocol {
func special()
}
class MyClass {}
class MyClassPlus: MyClass, SpecialProtocol {
func special() {
println("I'm special")
}
}
class MyContainer {
private var i: MyClass?
var test: MyClass? {
get {
return self.i
}
set (newValue) {
if newValue is SpecialProtocol {
self.i = newValue
}
}
}
}
var container = MyContainer()
println("should be nil: \(container.test)")
container.test = MyClass()
println("should still be nil: \(container.test)")
container.test = MyClassPlus()
println("should be set: \(container.test)")
(container.test as? MyClassPlus)?.special()
Outputs:
should be nil: nil
should still be nil: nil
should be set: Optional(main.MyClassPlus)
I'm special
(Optionally, you could also use precondition(newValue is SpecialProtocol, "newValue did not conform to SpecialProtocol") in place of the is check, but that will act like an assert() can crash the app if the case isn't met. Depends on your needs.)
#rintaro's answer is a good one, and is a good example of using a where clause as a guard (both nice functional-ly, and Swift-ly). However, I just hate to write a setFoo() function when computable properties exist. Then again, even using a computable property has code smell, since we can't seem to be able to apply a generic type-constraint to the set'er, and have to do the protocol conformance test in-line.
You can use typealias keyword. Here is how to do it:
typealias MyNewType = MyExistingType
It doesn't matter whether MyExistingType is protocol or function or enum. All it needs to be some type. And the best part is you can apply access control on it. You can say
private typealias MyNewType = MyExistingType
That makes MyNewType is only accessible the context that is defined in.

Resources