Make a globale variable not lazy - ios

I'm building a library in Swift and it has a global variable (global variables are automatically initialized lazy). Initializing this variable takes about one second. My problem is, I want to initialize the variable when the app is loading, so that the user doesn't have to wait later. My current approach is this:
My ViewController:
override func viewDidLoad() {
...
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), {
let _ = Foo()
})
}
My Framework File:
let myGlobalVariable = bar()
class Foo {
public init() {
myGlobalVariable
}
....
}
But this approach doesn't seam like it is the swiftlike way of doing it. How can I initialize the variable the right way?
Thx

There is no swift way to "when" you should init global vars in your framework , It depends on the flow of your framework , nothing in your framework will be called until it is used , there is no "FrameworkDidLaunch" method, it's a "static" code just like any other classes but in another module , it can even be just a bundle of resources ...
If you want to ensure that someone uses your framework the way you intented to then write it in the documentation and/or add a static method that has to be called before use like "MyFramwork.startMyFramework()" or if you need some info from user like API Key "MyFramwork.setApiKey(_:)" and use it to init global vars and assert if this method was called.

Related

How can I get a custom python type and avoid importing a python module every time a C function is called

I am writing some functions for a C extension module for python and need to import a module I wrote directly in python for access to a custom python type. I use PyImport_ImportModule() in the body of my C function, then PyObject_GetAttrString() on the module to get the custom python type. This executes every time the C function is called and seems like it's not very efficient and may not be best practice. I'm looking for a way to have access to the python custom type as a PyObject* or PyTypeObject* in my source code for efficiency and I may need the type in more than one C function also.
Right now the function looks something like
static PyObject* foo(PyObject* self, PyObject* args)
{
PyObject* myPythonModule = PyImport_ImportModule("my.python.module");
if (!myPythonModule)
return NULL;
PyObject* myPythonType = PyObject_GetAttrString(myPythonModule, "MyPythonType");
if (!myPythonType) {
Py_DECREF(myPythonModule);
return NULL;
}
/* more code to create and return a MyPythonType instance */
}
To avoid retrieving myPythonType every function call I tried adding a global variable to hold the object at the top of my C file
static PyObject* myPythonType;
and initialized it in the module init function similar to the old function body
PyMODINIT_FUNC
PyInit_mymodule(void)
{
/* more initializing here */
PyObject* myPythonModule = PyImport_ImportModule("my.python.module");
if (!myPythonModule) {
/* clean-up code here */
return NULL;
}
// set the static global variable here
myPythonType = PyObject_GetAttrString(myPythonModule, "MyPythonType");
Py_DECREF(myPythonModule);
if (!myPythonType) {
/* clean-up code here */
return NULL;
/* finish initializing module */
}
which worked, however I am unsure how to Py_DECREF the global variable whenever the module is finished being used. Is there a way to do that or even a better way to solve this whole problem I am overlooking?
First, just calling import each time probably isn't as bad as you think - Python does internally keep a list of imported modules, so the second time you call it on the same module the cost is much lower. So this might be an acceptable solution.
Second, the global variable approach should work, but you're right that it doesn't get cleaned up. This is rarely a problem because modules are rarely unloaded (and most extension modules don't really support it), but it isn't great. It also won't work with isolated sub-interpreters (which isn't much of a concern now, but may become more more popular in future).
The most robust way to do it needs multi-phase initialization of your module. To quickly summarise what you should do:
You should define a module state struct containing this type of information,
Your module spec should contain the size of the module state struct,
You need to initialize this struct within the Py_mod_exec slot.
You need to create an m_free function (and ideally the other GC functions) to correctly decref your state during de-initialization.
Within a global module function, self will be your module object, and so you can get the state with PyModule_GetState(self)

Dart extension: don't access members with 'this' unless avoiding shadowing

I'm learning to use the new Dart extension methods.
I'm doing this:
extension StringInsersion on StringBuffer {
void insertCharCodeAtStart(int codeUnit) {
final end = this.toString();
this.clear();
this.writeCharCode(codeUnit);
this.write(end);
}
int codeUnitAt(int index) {
return this.toString().codeUnitAt(index);
}
}
So that I can do something like this:
myStringBuffer.insertCharCodeAtStart(0x0020);
int value = myStringBuffer.codeUnitAt(2);
However, I get the following lint warning:
Don't access members with this unless avoiding shadowing.
Should I be doing something different?
The warning you received means the following:
There is no need to reference the current instance using keyword this. Everything will work without reference to the current instance because the static extension method itself acts as an instance method of extensible type.
Simply put, just remove the reference to the current instance from your code.
From this:
final end = this.toString();
To this:
final end = toString();
It's a style thing, based on Dart's guide. There are examples in https://dart-lang.github.io/linter/lints/unnecessary_this.html.
You can find more about style in https://dart.dev/guides/language/effective-dart/style.
I turn off this rule globally by changing "analysis_options.yaml"
include: package:flutter_lints/flutter.yaml
linter:
rules:
unnecessary_this: false

How can I test a private or fileprivate function in project

I want to write some unit testing code for a manager class, the function I would write for is using some small private functions. I will prepare a lot if I testing the public function, so I want to test those private functions. But in test target I can't call the private function directly.
So I wanna ask, is there's a way to test them without change them from private to internal or public?
So I wanna ask, is there's a way to test them without change them from private to internal or public?
Add an internal function that does nothing but call the private function. Probably it's best to do it in an extension:
class Foo
{
fileprivate func myPrivateFunction(p: Int) { ... }
}
extension Foo
{
internal func testMyPrivateFunction(p: Int)
{
myPrivateFunc(p: p)
}
}
You can probably find a way of using conditional compilation to omit the extension for release builds e.g.
#if DEBUG
extension Foo
{
internal func testMyPrivateFunction(p: Int)
{
myPrivateFunc(p: p)
}
}
#endif
Not tested the conditional thing to see if it works, it's borrowed from here https://ericasadun.com/2018/04/18/forcing-compiler-errors-in-swift/
Sadly no. There isn't a "VisibleForTesting" tag in Swift as there is in java.
However you can define a protocol which your manager class then implements including only the methods you want to test.
For example if your manager has a function called createViewModel that calls several private methods testing that the viewModel created matches that of what we expect we have implicitly tested the private methods work. You can set up your manager with different initial conditions to test all varieties and edge cases
I think you are looking for #testable imports. From Apple's documentation:
When you add the #testable attribute to an import statement for a
module compiled with testing enabled, you activate the elevated access
for that module in that scope. Classes and class members marked as
internal or public behave as if they were marked open. Other entities
marked as internal act as if they were declared public.
Interfaces are the solution.
This solution is a bit more complicated than the others, but can help you for multiple purposes, like uncoupling modules on your app.
Let's say you have a class Foo which has an object of type Bar, and you need to call doStuff().
Create a Protocol for Bar. So Foo is decoupled from Bar and becomes fully testable without exposing its content to Foo. Something like this:
protocol BarProtocol {
func doStuff()
}
class Bar:BarProtocol {
func doStuff() {
print("Hello world")
}
}
class Foo {
var bar:BarProtocol
init() {
self.bar = Bar()
self.bar.doStuff()
}
}

in Dart, problems when attempting to "register" sub-class with super-class

I wish to have the sub-classes of a super-class "registered" by an arbitrary name - whenever I declare a sub-class I wish to also have it entered into the super-class.sub Map.
Is there any way to accomplish this outside of main()?
// base class
class Mineral{
final String formula;
static Map<String,Mineral> sub = {}
Mineral( this.formula );
}
// sub class - declare and register
class Mica extends Mineral{
Mica( String formula ) : super( formula );
}
Mineral.sub['mica'] = Mica; // oops!
when I run this, I get
Error: line 10 pos 1: unexpected token 'Mineral' Mineral.sub['mica'] = Mica;
assuming that executable code is not allowed outside main().
cannot put within the super-class since other sub-classes may declared later, outside the library.
Dart has no way to run code as part of a library being loaded.
Executable code can only be put inside methods, or in field initializers, and static field initializers are lazy so they won't execute any code until you try to read them.
This is done to ensure quick startup - a Dart program doesn't have to execute any code before starting the main library's "main" method.
So, no, there is no way to initialize something that isn't constant before main is called.
Either
Mineral.sub['mica'] = new Mica();
or
static Map<String,Type> sub = {};
When you assign Mica you assign the Type Mica. new Mica() is an instance of Mica that is of the kind Mineral and can be assigned to the map you declared.
edit
Maybe you want to initialize the sub map:
static Map<String,Mineral> sub = {'mica': new Mica()};
hint: the semicolon is missing in this line in your question.

Using mirrors, how can I get a reference to a class's method?

Say I have an instance of a class Foo, and I want to grab a list of all of its methods that are annotated a certain way. I want to have a reference to the method itself, so I'm not looking to use reflection to invoke the method each time, just to grab a reference to it the first time.
In other words, I want to do the reflection equivalent of this:
class Foo {
a() {print("a");}
}
void main() {
var f = new Foo();
var x = f.a; // Need reflective way of doing this
x(); // prints "a"
}
I have tried using InstanceMirror#getField, but methods are not considered fields so that didn't work. Any ideas?
As far as I understand reflection in Dart, there's no way to get the actual method as you wish to. (I'll very happily delete this answer if someone comes along and shows how to do that.)
The best I can come up with to ameliorate some of what you probably don't like about using reflection to invoke the method is this:
import 'dart:mirrors';
class Foo {
a() {print("a");}
}
void main() {
var f = new Foo();
final fMirror = reflect(f);
final aSym = new Symbol('a');
final x = () => fMirror.invoke(aSym, []);
x(); // prints "a"
}
Again, I know that's not quite what you're looking for, but I believe it's as close as you can get.
Side note: getField invokes the getter and returns the result -- it's actually fine if the getter is implemented as a method. It doesn't work for you here, but for a different reason than you thought.
What you're trying to get would be described as the "closurized" version of the method. That is, you want to get the method as a function, where the receiver is implicit in the function invocation. There isn't a way to get that from the mirror. You could get a methodMirror as
reflect(foo).type.methods[const Symbol("a")]
but you can't invoke the result.

Resources