Get Class from External Library's Binary - ios

Is it possible to get a class from an external library's binary in ObjC?
Like i kno the name of the class, and im just tryna test a view to see if its a type of class
ive tried forward declarations, but that didnt work
for instance:
if([subview isKindOfClass:[ExternalBinaryView class]])
{
ExternalBinaryView* _foo = subview;
}
thanks for the help in advance

If the header files aren't supplied use NSClassFromString.
if([subview isKindOfClass:NSClassFromString(#"ExternalBinaryView")])
{
ExternalBinaryView* _foo = subview;
}

Import the header file for that class:
#import <LibraryName/ExternalBinaryView.h>
Or if there's a common header to import everything:
#import <LibraryName/LibraryName.h>
Your code should then work as expected.

Related

How to parsing custom function in Source insight?

My function definition and prototype as below, have anyone know how to set the custom parse to link definition and prototype of FuncConnect?
Thanks.
extern FUNC(void, CODE) FuncConnect (void);
FUNC(void, CODE) FuncConnect (void)
{
// do something
}

Swift Framework <-> ObjC interoperation

I've got a dylib framework with some UIView subclasses made in swift which I've done to use the new #IBDesignable and #IBInspectable stuff.
So lets say I've got a UITextField subclass in there named MyTextField.swift like this:
MyTextField.swift
#IBDesignable class MyTextField: UITextField {
// some properties etc.
// content is irrelevant
}
Now it compiles and works well in InterfaceBuilder so far so good. But what I need to do is import this special subclass into my Objective C implementation of the controller to set a property in code at runtime.
The framework (named myViews) has a header called myViews.h which I am able to import into the controllers header like this:
MyViewController.h:
#import myViews;
#import <UIKit/UIKit.h>
#import "myViews.h"
#interface MyViewController : UIViewController
#property(weak, nonatomic) IBOutlet MyTextField *txtName; // <-- This is the problem!
#end
This is where I'm stuck! So the class MyTextField is unknown from the imported headers. The myViews.h was automatically generated. I've tried to import the bridging-headers in there without success.
myViews.h:
#import <UIKit/UIKit.h>
//! Project version number for myViews.
FOUNDATION_EXPORT double myViewsVersionNumber;
//! Project version string for myViews.
FOUNDATION_EXPORT const unsigned char myViewsVersionString[];
// In this header, you should import all the public headers of your framework
// using statements like #import <myViews/PublicHeader.h>
#import <myViews/MyTextField-Swift.h> // <-- This is what I've tried to import here which doesn't work as well.
Hope anybody may help me out. Thanks in advance.
In your objective-c class, try importing your swift module like this:
#import "<ModuleName>-Swift.h"
Where ModuleName is the name of the module containing the swift code

Cannot access variables in a Swift class from Objective-C file

I'm trying to continue with Swift in an existing project I had started in Objective-C. I followed the Apple documentation and I managed to access a Swift class from an Objective-C file, via including the "ProductModuleName-Swift.h" header in my Obj-C file.
At this point here's my code:
#include "Pianoconcert_App-Swift.h"
#interface ModelsVC ()
#end
#implementation ModelsVC
// And all that kind of stuff
// ...
-(IBAction)comanda:(UIButton *)sender {
ComandaTableVC *controller = (ComandaTableVC *)self.tabBarController.viewControllers[2];
// Here goes the problematic code
[self.tabBarController setSelectedIndex:2];
}
This piece of code has no problems. But now I just want to set one of the variables in the Swift class like this: controller.selectedModel = sender.tag, but Xcode just tells me the variable does not exist.
Here's an extract of my Swift class:
import UIKit
class ComandaTableVC: UITableViewController, UIPickerViewDataSource, UIPickerViewDelegate {
// Declaration of some constants and variables
// And here goes the one
var selectedModel: Int = 0
// And a bunch more of variables and functions
// ...
}
I don't know what I'm doing wrong. The class seems fully included and, actually, I can access that variable and all the others if I use the class from another Swift file, like this:
var controller: ComandaTableVC = self.tabBarController.viewControllers[2] as ComandaTableVC
controller.selectedModel = 2
It's been resolved finally, but I can't explain how.
Suddenly the compiler threw a build error telling me that the file Pianoconcert_App-Swift.h could not be found.
I changed it for PianoconcertApp-Swift.h, deleting the underscore that replaced the blank space, and now I can access all the variables and constants correctly.

When to declare something in category .m file or in header .h file? [duplicate]

This question already has answers here:
Why is there another #interface inside the.m file? [duplicate]
(6 answers)
Closed 9 years ago.
As we know, normally we used to declare our class instance variables, properties, method declarations in class header file (.h).
But we can do the same things, in .m file, using blank category.
So my question is: what should be declared in .h file and what should be declared in .m file - and why?
Regards,
Mrunal
New Edit:
Hi all,
If you refer to newly added Apple examples over developer.apple.com - they are now declaring their IBOutlets and IBActions in .m file itself and that too with property declaration. But we can achieve the same thing by declaring those references in .h file in class private member section.
Then why are they declaring those in .m file and as properties, any idea?
-Mrunal
But we can do the same things, in .m file, using blank category.
A class continuation.
Normally, you choose to declare something in the header if it is intended to be public -- used by any client. Everything else (your internals) should typically go in the class continuation.
I favor encapsulation -- Here's my approach:
variables
Belongs in the class continuation or #implementation. Exceptions are very, very rare.
properties
Typically belongs in the class continuation in practice. If you want to give subclasses the ability to override these or to make these part of the public interface, then you could declare them in the class declaration (the header file).
method declarations
More in the class continuation than in the class declaration. Again, if it is meant to be used by any client it would belong in the class declaration. Often, you won't even need a declaration in the class continuation (or class declaration) -- the definition alone is adequate if it is private.
Basically, in the header file (.h) you declare your public API, while in the implementation file (.m) you declare your private API.
Visibility in Objective-C
You can also find the answer here
It's mostly up to you.
The .h file is like the description of your class.
It's smart to only put in the .h file what's really important to be visible from the outside of the class, especially if you're working with other developers.
It will help them to understand more easily what methods/properties/variables they can use, rather than having a whole list of things they don't.
Usually you want to use blank category in .m file for declaration of private properties.
// APXCustomButton.m file
#interface APXCustomButton ()
#property (nonatomic, strong) UIColor *stateBackgroundColor;
#end
// Use the property in implementation (the same .m file)
#implementation APXCustomButton
- (void)setStyle:(APXButtonStyle)aStyle
{
UIColor *theStyleColor = ...;
self.stateBackgroundColor = theStyleColor;
}
#end
If you try to access property declared in black category outside .m file, you will receive undeclared property compiler error:
- (void)createButton
{
APXCustomButton *theCustomButton = [[APXCustomButton alloc] init];
theCustomButton.stateBackgroundColor = [UIColor greenColor]; // undeclared property error
}
In most cases, if you want add new method/properties to an existing class without subclassing, then you want declare category in .h file and implementation of declared methods in .m file
// APXSafeArray.h file
#interface NSArray (APXSafeArray)
- (id)com_APX_objectAtIndex:(NSInteger)anIndex;
#end
// APXSafeArray.m file
#implementation NSArray
- (id)com_APX_objectAtIndex:(NSInteger)anIndex
{
id theResultObject = nil;
if ((anIndex >= 0) && (anIndex < [self count]))
{
theResultObject = [self objectAtIndex:anIndex];
}
return theResultObject;
}
#end
Now you can use "com_APX_objectAtIndex:" method wherever "APXSafeArray.h" is imported.
#import "APXSafeArray.h"
...
#property (nonatomic, strong) APXSafeArray *entities;
- (void)didRequestEntityAtIndex:(NSInteger)anIndex
{
APXEntity *theREquestedEntity = [self.entities com_APX_objectAtIndex:anIndex];
...
}

how do I make an objective-c delegate for a cpp class?

I'm stuck trying to combine openGL-es (xcode openGL game template with the ogles2tools library from powervr 3.0 sdk. My problem is the line of code where I load the effect file:
/*
Load the effect.
We pass 'this' as an argument as we wish to receive callbacks as the PFX is loaded.
This is optional and supplying NULL implies that the developer will take care
of all texture loading and binding to to the Effect instead.
*/
if(m_pEffect->Load(*m_pEffectParser, "Effect", c_szPfxFile, NULL, uiUnknownUniforms, &error) != PVR_SUCCESS)
{
NSLog(#"%s",error.c_str());
return;
}
I'm supposed to pass a "this" pointer so I can receive the callbacks. The delegate method I need to implement is:
EPVRTError OGLES2IntroducingPFX::PVRTPFXOnLoadTexture(const CPVRTStringHash& TextureName, GLuint& uiHandle, unsigned int& uiFlags)
{
/*
This is an optional callback function for PVRTPFXEffect and can be used to automate
the texture loading process.
If multiple effects are to be loaded and they share textures it would be
prudent to have a caching system in place so texture memory is not wasted.
Please see OGLES2MagicLantern for an example of this.
*/
if(PVRTTextureLoadFromPVR(TextureName.String().c_str(), &uiHandle) != PVR_SUCCESS)
return PVR_FAIL;
return PVR_SUCCESS;
}
I guess the big issue for me is how do I go about providing a cpp delegate method in objective-c? I did some reading on this issue, but it seemed what I was reading was going the other way. That is, an objective-c delegate in cpp. It's pretty confusing, but here's my thought...
I create a cpp class the implements the method I need. I add that to my viewController class and pass the pointer to this cpp class in the m_pEffect->Load call. Does this seem correct?
Thanks.
P.S. Sorry if my code formatting is bad. I'm still learning.
Edit: Here's the example I found regarding mixing the objective-c and cpp. It seems really similar to what I want to do.
Update: Here's some additional info (requested by user1118321)
The CPP class which needs a delegate is CPVRTPFXEffect (PVRTPFXParserAPI.h - from powerVR SDK 3.0). I would add a link, but I'm not sure if this is allowed. Here's a link to the class header, but this version (and others on the web) did not include the pDelegate attribute for the load method. I'm assuming they are examples of a previous version. Let me know if it's okay to post this class file and I will do so.
I found a good example of what I think I'm supposed to do from reading this thread. So here's what I have so far:
My CPP delegate class...
class myCppDelegate : public PVRTPFXEffectDelegate {
public:
myCppDelegate() {};
EPVRTError PVRTPFXOnLoadTexture(const CPVRTStringHash& TextureName, GLuint& uiHandle, unsigned int& uiFlags) {
return PVR_FAIL;
};
};
My Obj-C wrapper class (just modified from the example link above)...
struct RNWrapOpaque;
#interface RNWrap : NSObject {
struct RNWrapOpaque *_cpp;
}
- (id)init;
#end
implementation...
#import "RNWrap.h"
#import "Wrap.h"
#interface RNWrap ()
#property (nonatomic, readwrite, assign) RNWrapOpaque *cpp;
#end
#implementation RNWrap
#synthesize cpp = _cpp;
struct RNWrapOpaque
{
public:
RNWrapOpaque() : wrap() {};
myCppDelegate wrap;
};
- (id)init
{
self = [super init];
if (self != nil)
{
self.cpp = new RNWrapOpaque();
}
return self;
}
- (void)dealloc
{
delete _cpp;
_cpp = NULL;
// [super dealloc];
}
#end
Basically I am able to compile the code and debug, but when the the CPVRTPFEffect class makes this call:
if(pDelegate->PVRTPFXOnLoadTexture(pTexDesc->FileName, uiHandle, uiFlags) != PVR_SUCCESS)
I get EXC_BAD_ACCESS. I'm assuming it's not finding my callback method, because I set a breakpoint and the line never gets called.
Here's my updated code which calls CPVRTPFXEffect::Load using a bridge command for the delegate parameter.
if(m_pEffect->Load(*m_pEffectParser, "Effect", c_szPfxFile,(__bridge myCppDelegate*)opaqueCppWrap, uiUnknownUniforms, &error) != PVR_SUCCESS)
Thanks for your help!
Update 2: The project uses ARC. Here's what my viewController interface looks like:
#interface ViewController : GLKViewController {
...
RNWrap* opaqueCppWrap;
...
}
#property (strong) RNWrap *opaqueCppWrap;
Adding the #property didn't help with the EXC_BAD_ACCESS. I'm not sure how to "see" the value of pDelegate when I'm tracing the CPP code. Xcode doesn't reveal anything when I hover over the variable.
I added the following line of code to the CPVRTPFXEffect::Load method (just prior to the line where it crashes):
*pReturnError += PVRTStringFromFormattedStr("Here is your class typeid: %s.\n", typeid(pDelegate).name());
return PVR_FAIL;
This is what displayed in the debug output window:
Here is your class typeid: P21PVRTPFXEffectDelegate.
I'm not sure what the "P21" means (if anything), but it looks like I'm close to getting this working. I dunno, maybe this is as close as it gets. Still crashing and not finding my method.
First, you may want to look at the last article in the series on wrapping C++. Most of it has gotten much simpler in the latest versions of clang. You probably don't need half this code anymore. ObjC++ objects can now have private C++ properties without any tricks, while maintaining a pure-ObjC interface.
Here is how you want to think about this problem:
Build a C++ object that is the delegate. Write all the code involved in setting up the delegation, etc, in C++. So when it says "pass a this pointer" you should really be passing a this pointer (because you should be doing this in the C++ code). The fact that you're doing a _bridge cast in a C++ call is a real hint something is going wrong.
Let an ObjC own the C++ object as a property.
Write the delegate callbacks in C++ inside the C++ object. If useful, you can let the C++ object then make calls into the ObjC object as needed, but it may be easier if the C++ object does all the delegate work.
I finally got this working, but had to remove the obj-c wrapper class from my viewController in order to do so. Here's what the code looks like:
ViewController.h
struct Opaque;
#interface ViewController : GLKViewController {
...
//RNWrap* opaqueCppWrap; // this didn't work
struct Opaque *opaqueCpp; // try this
...
}
ViewController.mm
// declare the Opaque structure
struct Opaque {
public:
Opaque() : cppobject() {};
myCppDelegate cppobject;
};
viewDidLoad
// ... create opaque member on initialization
opaqueCpp = new Opaque();
//opaqueCppWrap = [[RNWrap alloc] init]; // old way of doing things using wrapper
pass the delegate to the Load method
// old way using bridge cast and wrapper
//if(m_pEffect->Load(*m_pEffectParser, "Effect", c_szPfxFile,(__bridge myCppDelegate*)opaqueCppWrap, uiUnknownUniforms, &error) != PVR_SUCCESS)
// this works...
if(m_pEffect->Load(*m_pEffectParser, "Effect", c_szPfxFile, (myCppDelegate*)opaqueCpp, uiUnknownUniforms, &error) != PVR_SUCCESS)
Not sure why the wrapper class doesn't work, but I'm happy that my callback is working (appy no crashy!)
Phew, that was rough. Any thoughts/comments?

Resources