Registering setup code in objective-c - ios

Is there a standard mechanism with Objective C and the iOS runtime to register setup code?
Why?
The advantage of this is that you can decouple your code nicely.
If a subsystem needs particular setup, the set up stays in that subsystem.
If a group of files need to register that they should all be offered as a particular service, that can be encapsulated in individual files that offer the service and there is no need for a separate configuration file to be kept up to date.
Getting the code to run isn't especially important – I can do that myself with various entry points. What I need is for the compiler or linker or run time or magic to be able to collect up anything that I've registered in different parts of a program, and let me have it when I need it.
How to in c++
With c++, I've typically arranged for this with static instances that are constructed before main() is called. I could use objective-c++, but I'd much prefer to use a standard mechanism.
Thanks.

I would look up:
+ (void)initialize
This method is called whenever a message is first sent to the class meta-object, such as, for example, when alloc-ing an object of that class.

Registering Code
Use the class method +(void) load for components that need to self register themselves.
Note that the load method is run on all subclasses and all categories. This is nothing like the the normal method calling behaviour.
Creating a Registry
If components need to register themselves in some kind of container, use the class method +(void) initialise to create a container to hold the components that are going to register themselves. It seems from my limited testing that initialize can be called before load when a load method uses a class with an initialize method, which is pretty cool if reliable.
Running Registered Code
If the components should do something at some specific entry point of your App, then at that entry point, grab the registered components from the registry and do that thing. Eg, you might extend you UIApplicationDelegate's -(BOOL) application:didFinishLaunchingWithOptions: to actually perform the setup stages the components registered.
In my case, I actually want the registered code to get run every time a specific kind of object is constructed, so I call the registered methods there and let them have the object being constructed.
More references on load and initialise
Thank you for the answers and comments that let me put this answer together.
Quite a lot of detail from Mike Ash, although I was initially put off by his statements about load being "tricky because it runs so early".
A very helpful S.O. question on load and initialize.

Related

How to check if a method is available in an OCX interface

Currently I have an OCX embedded in our product using standard boilerplate Delphi importing of the OCX. The vendor has issued a new version of the OCX that uses the exact same GUIDs for everything (object and interfaces) but there are changes to the API. These changes are quite limited but I'm having some difficulty coming up with a reliable way to identify if the installed OCX is using the old or new version. The obvious way is to drill into the interface and check if a specific method is available from the object once it has been instantiated. I would like to do this by actually asking the object what the dispatch ID is for a particular method to see if it is present.
I don't want to use the approach of calling a new method and getting an exception as the object won't work until it has been initialised and the initialisation API is one of the things that has changed. This means that any call of a new method before initialisation will fail anyway.
Does anyone know what would be the proper way to poke through the Delphi wrapper and find out if a particular method can be resolved?
The answer is actually in your question:
I would like to do this by actually asking the object what the dispatch ID is for a particular method to see if it is present.
An OCX object implements the IDispatch interface, and IDispatch has a GetIDsOfNames() method for the very purpose of returning the dispatch ID of the object's methods and properties (for use with IDispatch.Invoke()). If a requested name is not known to the object, GetIDsOfNames() returns DISP_E_UNKNOWNNAME.

ios - swizzling of firebase cloud messing

I am working with an app using Firebase Cloud Messaging for Push Notification. After reading its documentation, I have a little confuse about "Swizzling disabled", I tried to find some tutorials which are talking about it, but unfortunately there is no any tutorials. Could you please help me to describe what exactly "swizzling" mean? and what is case we need to use it?
Thank you so much.
Ryan
Method swizzling means that you change the implementation of a given function at runtime.
It is often used when you don't have access to the code of the function or if you don't want to modify the code of a library and when inheritance doesn't apply.
Basically what Firebase does: you don't have access to the Push Notifications API/functions except for the delegates that Apple exposes. By swizzling such a function, you can add some logic to what it is currently doing. (You can still call the "previous" function like you would do with super or completely replace its original purpose).
This is how Firebase asks you to activate PUSH Notifications. It makes it easier for you to add it in your code and give Firebase a lot of flexibility as with one line in your AppDelegate they can run whatever they want.
NB: A simple example: you don't have access to the print function, you can just use it. Instead of wrapping the print function in a custom function and replacing its usage everywhere; you could swizzle print with one of your custom function to extend or replace its original functionality. As it is applied at runtime, you wouldn't have to change anything in your project and all print calls would be "redirected" to your new custom function.

Keeping a WKWebView and it's UIViewController in the background running and accessible from multiple ViewControllers

Background: In order to make web requests to an API endpoint, I need to scrape a website and retrieve a token every 25-30 seconds. I'm doing this with a WKWebView and injecting some custom JavaScript using WKUserScript to retrieve AJAX response headers containing the token. Please focus on the question specifically and not on this background information - I'm attempting this entirely for my own educational purposes.
Goal
I will have different 'model' classes, or even just other UIViewControllers, that may need to call the shared UIViewController to retrieve this token to make an authenticated request.
Maybe I might abstract this into one "Sdk" class. Regardless, this 'model' SDK class could be instantiated and used by any other ViewController.
More info
I would like to be able to call the UIViewController of the WKWebView and retrieve some data. Unless I re-create it every 25 seconds, I need to run it in the background or share it. I would like to be able to run a UIViewController 'in the background' and receive some information from it once WKWebView has done it's thing.
I know there are multiple ways of communicating with another ViewController including delegation and segueing. However, I'm not sure that these help me keep the view containing the WKWebView existing in the background so I can call it's ViewController and have it re-perform the scrape. Delegation may work for normal code, but what about one that must have the view existing? Would I have to re-create this WKWebView dynamically each time a different model, or view controller, were to try and get this token?
One post suggests utilising ContainerViewControllers. From this, I gather that in the 'master' ViewController (the one containing the other ones), I could place the hidden WKWebView to do it's thing and communicate to the child view controllers that way via delegation.
Another post suggests using AppDelegate and making it a shared service. I'm completely against using a Singleton as it is widely considered an anti-pattern. There must be another way, even if a little more complex, that helps me do what I want without resorting to this 'cheat'.
This post talks about communicating between multiple ViewControllers, but I can't figure out how this would be useful when something needs to stay running and executing things.
How about any other ways to do this? Run something in a background thread with a strong pointer so it doesn't get discarded? I'm using Xcode 9.2, Swift 4, and iOS 11. As I'm very new to iOS programming, any small code examples on this would be appreciated.
Unfortunately, WKWebView must be in the view hierarchy to use it. You must have added it as a sub view of an on-screen view controller.
This was fine for me. I added this off-screen so it was not visible. Hidden attribute might have worked as well. Either way you must call addSubview with it to make it work.
There are some other questions and answers here which verify this.
Here is a way if you don't wish to use a singleton.
1- In the DidFinishlaunchingWithOptions, Make a timer that runs in the background and call a method inside the app delegate Called FetchNewToken.
2- In FetchNewToken, make the call needed and retrieve the new token (you can use alamofire or any 3rd library to make the call easier for you).
Up on successfully retrieving the token, save it in NSUserDefaults under the name upToDateToken
You can access this token anywhere from the application using NSUserDefaults and it will always be up to date.

Why Apple suggests use your own NSFileManager when you use NSFileManagerDelegate?

In apple docs of defaultManager they say:
This method always returns the same file manager object. If you plan to use a delegate with the file manager to receive notifications about the completion of file-based operations, you should create a new instance of NSFileManager (using the init method) rather than using the shared object.
I just want to know that why they suggest to use a new instance of NFileManager when you use a delegate of the file manager?What's wrong if I use the shared file manager to do this?
The only thing I can see is that your delegate object will receive a lot of notifications that you don't want to know, is anything else?
Your last paragraph is pretty much it. If you set the delegate on the shared file manager, your delegate ends up getting called way more than you want. By creating a specific instance of NSFileManager and setting that instance's delegate, then you know the delegate methods are only being called for that specific use of the file manager and not all of the default uses.
Keep in mind that the default file manager instance could be used by a lot more than your own code. Lots of other libraries and frameworks will be using it as well.

How do I access the source level definition of classes at runtime?

How do I access the Objective-C class interface defanition that is collected from headers at (pre or actual) compile time so I can provide introspection that is true to the defined public interface.
Problem: F-Script, SuperDB, IKBClassBrowser, CBIntrospection use the class_copyPropertyList() family of functions to introspect objects at run time. While powerful, there are drawbacks…
the runtime has no concept of private and public… everything is
returned
I can not see a reliable way to access the to the ObjC types of
method arguments and returns
Goal: I am researching a iOS app to help teach coding via a live / immediate development environment (similar to SmallTalk, F-Script, SuperDB, IKBClassBrowser, CBIntrospection). I want users to introspect objects, send messages, create new objects, and build and run code via a VM. But I want to limit the functionality to public functions (there is no way Apple would approve the app otherwise) and I want to have access to types so I limit so users can only pass legal objects.
My hope is that there is some way to access Clang or the symbol file to pull this information in way I can use it at runtime. It does not have to be fully automated (I will probably want to limit functionality in some ways)
You're encountering one of the distinguishing characteristics of Objective-C: There is no such thing as private or public API. There's only documented API vs. undocumented API. You can call any method on any object at any time, regardless of whether it appears in a header file. Public/private distinctions exist only for the compiler; at run time, they don't exist, and there's no way to reverse the process and discern what the header files might have said.

Resources