Overriding CALayer's initWithLayer in Swift - ios

I'm learning how to use CALayers and perform animations on their properties. To a beginner Apple's documentation is simply cryptic. I managed to find an example (called: CustomAnimatableProperty) in iOS's documentation which somewhat 'explains' how to do what I want:
// For CALayer subclasses, always support initWithLayer: by copying over custom properties.
-(id)initWithLayer:(id)layer {
if( ( self = [super initWithLayer:layer] ) ) {
if ([layer isKindOfClass:[BulbLayer class]]) {
self.brightness = ((BulbLayer*)layer).brightness;
}
}
return self;
}
Translating the method override to Swift however gives me a few errors:
The errors stem from my lacking understanding of what's going on here. I'm not sure what are we checking for in those nested if statements. Also I am a bit baffled by the usage of "=" in the main if(){} block. Shouldn't we be checking ("==") for equality?
But yeah any general help would mean the world. I've tried reviewing a few blog-posts / tutorials online, however non of them deals with this speciffic issue.

The self = [super init...] idiom is for Objective-C, not Swift. In Swift, init blocks aren't normal functions and don't return anything.
While we're at it, let's use the Swift idiom for downcasting. We also need to guarantee that size is initialized before we call super.init.
override init(layer: AnyObject!) {
if let layer = layer as? SegmentActiveLayer {
size = layer.size
} else {
size = 0
}
super.init(layer: layer)
}

Related

Memory Leak Kotlin Native library in iOS

I'm building a Kotlin library to use in my iOS app using Kotlin/Native. After I call some methods in the library from Swift, which works, I also want to call methods in Swift from the library. To accomplish this I implemented an interface in the library:
class Outbound {
interface HostInterfaceForTracking {
fun calcFeatureVector(bitmap: Any?): Array<Array<FloatArray>>?
}
var hostInterface: HostInterfaceForTracking? = null
fun registerInterface(hostInterface: HostInterfaceForTracking) {
this.hostInterface = hostInterface
instance.hostInterface = hostInterface
}
}
This is implemented on the Swift side like this:
class HostInterfaceForTracking : OutboundHostInterfaceForTracking {
var t : Outbound? = nil
init() {
TrackingWrapper.instance?.runOnMatchingLibraryThread {
self.t = Outbound()
self.t!.registerInterface(hostInterface: self)
}
}
func calcFeatureVector(bitmap: Any?) -> KotlinArray<KotlinArray<KotlinFloatArray>>? {
do {
var test : Any? = (bitmap as! Bitmap).bitmap
return nil
} catch {
return nil
}
}
}
The TrackingWrapper looks like this:
class TrackingWrapper : NSObject {
static var instance: TrackingWrapper? = nil
var inbound: Inbound? = nil
var worker: Worker
override init() {
self.worker = Worker()
super.init()
initInboundInterface()
}
func initInboundInterface() {
runOnMatchingLibraryThread {
TrackingWrapper.instance = self
self.inbound = Inbound()
HostInterfaceForTracking()
}
}
func runOnMatchingLibraryThread(block: #escaping() -> Void) {
worker.enqueue {
block()
}
}
}
The function runOnMatchingLibraryThread is needed because every call to the TrackingLibrary needs to be called from the exact same thread, so the Worker class initializes a thread and enqueues every method to that thread.
The Bitmap in this case is simply a wrapper for an UIImage, which I already accessed with the .bitmap call, so I've tried to access the wrapped UIImage and save it in the test variable. The library gets the current camera frame from the Swift side every few frames and sends the current image wrapped as a Bitmap to the method calcFeatureVector depicted here.
Problem: My memory load starts increasing as soon as the app starts until the point it crashes. This is not the case if I don't access the wrapped UIImage (var test : Any? = (bitmap as! Bitmap)). So there is a huge memory leak, just by accessing the wrapped variable on the Swift side. Is there anything I've missed or is there any way to release the memory?
Looks like you have a circular dependency here:
TrackingWrapper.instance?.runOnMatchingLibraryThread {
self.t = Outbound()
self.t!.registerInterface(hostInterface: self)
}
You are asking a property inside HostInterfaceForTracking to maintain a strong reference to the same instance of HostInterfaceForTracking. You should be using [weak self] to avoid the circular reference.
EDIT:
Ok after seeing the rest of you code theres a lot to unpack. There is a lot of unnecessary bouncing back and forth between classes, functions and threads.
There is no need to use runOnMatchingLibraryThread to just create an instance of something. You only need to use that for the code processing the image itself (I would assume, I haven't seen anything so far that requires being split off into another thread). Inside TrackingWrapper, you can create a singleton more easily, and matching the swift pattern by simply doing this as the first line:
static let shared = TrackingWrapper()
And everywhere you want to use it, you can just call TrackingWrapper.shared. This is more common and will avoid one of the levels of indirection in the code.
I'm not sure what Worker or Inbound are, but again these can and should be created inside the TrackingWrapper init, rather than branching Inbound's init, to use another thread.
Inside initInboundInterface you are creating an instance of HostInterfaceForTracking() which doesn't get stored anywhere. The only reason HostInterfaceForTracking is continuing to stay in memory after its creation, is because of the internal circular dependency inside it. This is 100% causing some form of a memory issue for you. This should probably also be a property on TrackingWrapper, and again, its Init should not be called inside runOnMatchingLibraryThread.
Having HostInterfaceForTracking's init, also using runOnMatchingLibraryThread is problematic. If we inline all the code whats happening is this:
TrackingWrapper
init() {
self.runOnMatchingLibraryThread {
TrackingWrapper.instance = self
self.inbound = Inbound()
TrackingWrapper.instance?.runOnMatchingLibraryThread {
self.t = Outbound()
self.t!.registerInterface(hostInterface: self)
}
}
}
Having all these classes unnecessarily keep coming back to TrackingWrapper is going to cause issues.
Inside HostInterfaceForTracking 's init, no need to be creating Outbound on a separate thread. First line in this class can simply be:
var t : Outbound = OutBound()
Or do it in the init if you prefer. Either way will also remove the issue of needing to unwrap Outbound before using it.
Inside Outbound you are storing 2 references to the hostInterface instance:
this.hostInterface = hostInterface
instance.hostInterface = hostInterface
I would have imagined there should only be 1. If there are now multiple copies of a class that has a circular dependency, which has multiple calls to separate threads. This again will cause issues.
I'm still not sure on the differences between Swift and Kotlin. In Swift when passing self into a function to be stored, the class storing it would mark the property as weak, like so:
weak var hostInterface: ......
Which will avoid any circular dependency from forming. A quick google says this isn't how things work in Kotlin. It might be better to look into the swift side passing in a closure (lambda on kotlin) and the kotlin side executing that. This might avoid the need to store a strong reference. Otherwise you need to be looking into some part of your code setting hostInterface back to null. Again its a bit hard to say only seeing some of the code and not knowing how its working.
In short, it looks like the code is very over complicated, and needs to be simplified, so that all these moving pieces can be tracked easier.

Constant variable initialization based on IO operation with a condition

I've been programming some opencv app with kotlin and stumbled on a matter that I'm curious about based on the code below:
val image =
if (!Imgcodecs.imread(filename).empty())
Imgcodecs.imread(filename)
else
Mat.eye(512, 512, CvType.CV_8U).mul(Mat(512, 512, CvType.CV_8U, Scalar(255.0)))
Does compiler (in general) optimize such IO operations like these consecutive calls (imreads)?
What are the proven and / or elegant ways to deal with such problem?
I don't think the compiler has any way to know that an arbitrary method is side-effect free. And in fact this one isn't (I assume) - there's potential for a race condition here.
One way to avoid this is with something like this:
val image = with(Imgcodecs.imread(filename)) {
if (!empty()) {
this
} else {
Mat.eye(...)
}
}
Or something a bit more explicit, thus avoiding the magic of the with idiom:
val image = {
val mtx = Imgcodecs.imread(filename)
if (!mtx.empty()) {
mtx
} else {
Mat.eye(...)
}
}

swift check an object's property existence

I have the below UINib extension method, I was wondering if I can set a delegate for the unarchived view
public class func decodeView<T:UIView>(nibName name:String,className classType:T.Type,delegate:AnyObject) -> T {
let nib = UINib(nibName: name)
let topLevelObjects = nib.instantiateWithOwner(nil, options: nil)
let view = topLevelObjects[0] as T
view.setTranslatesAutoresizingMaskIntoConstraints(false)
//check if view.delegate exists then view.delegate = delegate
return view
}
If you're asking if Swift supports reflection, TL;DR: you need to subclass from NSObject. Else you get limited info.
In this question, Does Swift support reflection? you get a more detailed discussion about the possibilities you have.
Once you have this part cleared, an example of how to obtain a list of properties can be found in this SO Answer
Although a quick & dirty way could be just to try and access the property (using KVC) and catch the exception if it fails. Swift does NOT support Try/Catch/Finally constructs, but this nice hack allows you to write code like:
SwiftTryCatch.try({
// try something
}, catch: { (error) in
println("\(error.description)")
}, finally: {
// close resources
})

Writing getter and setter for BOOL variable

Obviously, with obj-c, there's usually no reason to write getters and setters (thanks to useful mr #synthesize).
So now, needing to do just this, I've come across the problem that I don't know how to write them. :p
I'm sure I'm probably not going about solving my problem the right way - it would be much easier to just subclass my object and such - but I'm trying to write category code to add properties because (in the beginning) it was quicker, and because I wanted to learn how to use category code in my app.
I've got this:
-(BOOL)isMethodStep {
return self.isMethodStep;
}
-(void)setIsMethodStep:(BOOL)theBoolean {
if(self.isMethodStep != theBoolean){
self.isMethodStep = theBoolean;
}
}
and I've tried it without the if query in the setter, but neither seem to work. Loading it with breakpoints shows that for some reason it gets stuck in a continuous loop in the getter method.
Is this code right or am I doing something wrong?
Thanks
Tom
In
-(BOOL)isMethodStep {
return self.isMethodStep;
}
return self.isMethodStep; calls the same isMethodStep method causing an infinite loop. Same thing for setter.
Just use your iVars directly in your accessor method implementations:
-(BOOL)isMethodStep {
return isMethodStep;
}
-(void)setIsMethodStep:(BOOL)theBoolean {
if(isMethodStep != theBoolean){
isMethodStep = theBoolean;
}
}
You don't want to use the self. property syntax within the setter/getter, because that invokes the setter/getter again, instead of directly assigning to the variable.
You need to just say:
-(BOOL)isMethodStep {
return isMethodStep;
}
-(void)setIsMethodStep:(BOOL)theBoolean {
isMethodStep = theBoolean;
}
(assuming "isMethodStep" is the name of your variable). I would omit the test in the setter method too...

iOS Identifying views in ObjC and Swift

What is the best practice to identify views in iOS?
For instance, you could have a lot of views that aren't worth subclassing because you need to work with just one subview in those views.
I like to use view tags, and for easy identification I would do like so for ObjC:
enum {
kViewTagSomeButton = 10,
kViewTagSomeOtherButton,
}
But to do this in Swift, this becomes quite verbose:
enum ViewTag: Int {
case SomeButton = 10, SomeOtherButton, ...
}
if view.tag == ViewTag.SomeButton.rawValue {
// Do something
}
Or should I use a completely different approach?
Edited
Changed the whole question to a more appropriate context

Resources