access private variable without creating a property - ios

Say, I have defined a private variable isStarted in MyService class & this class is a singleton:
#implementation MyService {
BOOL isStarted;
}
...
#end
My question:
Without creating property & accessors, is there a way to access this private variable from another class after I get a instance of this class [MyService sharedInstance]. If there is a way, could you please show me how? Thanks in advance.
(Please don't talk about "it is not recommended to do so" etc. I understand that. I am just curious about the possibility of accessing private field in objective-c in general. )

Hi again=) There is a way - you can get your all class variables on the runtime and there search needed one. Still that is hard way and not recommended. Why do you not want to use properties?
- (void*)getValueWithName:(const char*)varName forClass:(NSString*)className {
unsigned int varCount;
Class theClass = NSClassFromString(className);
Ivar *vars = class_copyIvarList(theClass, &varCount);
for (int i = 0; i < varCount; i++) {
Ivar var = vars[i];
const char* name = ivar_getName(var);
if (strcmp(name, varName) == 0) {
ptrdiff_t offset = ivar_getOffset(var);
unsigned char* bytes = (unsigned char *)(__bridge void*)self;
free(vars);
return (bytes+offset);
}
}
free(vars);
return NULL;
}
And casting value:
NSInteger t = *(NSInteger*)[self getValueWithName:"p" forClass:#"ViewController"];
BOOL checkBool = *(BOOL*)[self getValueWithName:"boolean" forClass:#"ViewController"];
NSString *checkString = *((__unsafe_unretained NSString **)([self getValueWithName:"string" forClass:#"ViewController"]));

I'm not sure if being a singleton makes this different, but here is a similar question.
According to this post, you can.
Accessing private variables from an external class - iOS
It's kind of old, but I'd give it a shot.
Specifically, this line
[object valueForKey:#"variable_name"];

Related

How to use a variable from a different class

I have a rather simple question. How can I use variables from different classes in dart?
class ContainsVariable {
var variable = 1;
}
class DoesNotContainVariable {
var useVariable = variable + 1; // This gives me an error saying:
// Undefined name 'variable'
}
Having their own scope is a very fundamental feature of classes in Object Oriented Programming, corresponding to OOP principles.
Also note that from your code, it seems that you have not properly understood the idea of instantiation in Object Oriented Programming, since you are trying to set an instance variable without instantiating the class. I highly suggest to look into this topic to gain more understanding.
That being said, there are most definitely many ways to achieve what you want. Since your code sample is very general, I'm not exactly sure what you are trying to do, so I'll provide 2 examples, which might be useful:
Option 1 - static member variable
You can make a static (class level) member, which will be the same for all objects.
class ContainsVariable {
static var variable = 1;
}
class DoesNotContainVariable {
var useVariable = ContainsVariable.variable + 1; // here, you are using a
// static (class) variable,
// not an instance variable.
// That is why you are using
// the class name.
}
Option 2 - instantiation
You can instantiate the class - by creating an object of that class - and access the member of that object. Notice that there is no static statement here.
class ContainsVariable {
var variable = 1;
}
class DoesNotContainVariable {
var instanceOfContainsVariable;
var useVariable;
DoesNotContainVariable(){ // this is a constructor function
var instanceOfContainsVariable = new ContainsVariable();
useVariable = instanceOfContainsVariable.variable + 1;
}
}

prevent reflection (objc/runtime) on iOS

I am working on a static library that handles sensitive data. It is imperative that the developer using the library can not use reflection on the library.
On Android, we solve the problem by developing an aar file with services and run the service into separate process;(When the service is running into another process then the developer can not use reflection) but I am wondering if something similar exists in iOS ?
Can we execute a static library into a separate process? if not, how we can avoid reflection on our static libraries?
For example:
MyTestObject *obj = [[[myTestView alloc] init ];
//===========================================
Class clazz = [obj class];
u_int count;
Ivar* ivars = class_copyIvarList(clazz, &count);
NSMutableArray* ivarArray = [NSMutableArray arrayWithCapacity:count];
for (int i = 0; i < count ; i++)
{
const char* ivarName = ivar_getName(ivars[i]);
[ivarArray addObject:[NSString stringWithCString:ivarName encoding:NSUTF8StringEncoding]];
}
free(ivars);
objc_property_t* properties = class_copyPropertyList(clazz, &count);
NSMutableArray* propertyArray = [NSMutableArray arrayWithCapacity:count];
for (int i = 0; i < count ; i++)
{
const char* propertyName = property_getName(properties[i]);
[propertyArray addObject:[NSString stringWithCString:propertyName encoding:NSUTF8StringEncoding]];
}
free(properties);
Method* methods = class_copyMethodList(clazz, &count);
NSMutableArray* methodArray = [NSMutableArray arrayWithCapacity:count];
for (int i = 0; i < count ; i++)
{
SEL selector = method_getName(methods[i]);
const char* methodName = sel_getName(selector);
[methodArray addObject:[NSString stringWithCString:methodName encoding:NSUTF8StringEncoding]];
}
free(methods);
NSDictionary* classDump = [NSDictionary dictionaryWithObjectsAndKeys:
ivarArray, #"ivars",
propertyArray, #"properties",
methodArray, #"methods",
nil];
NSLog(#"%#", classDump);
//======================================================
int v2 = [[obj valueForKey:#"testValue"] intValue];
SEL s = NSSelectorFromString(#"wannatTestIt");
[obj performSelector:s];
MyTestObject is a class from my library. In the first line, I initialize an object from this class.
In the next line, I read the variables, methods and property list of the class and log it. Here is the result:
{
ivars = (
testValue
);
methods = (
printTestValue,
wannatTestIt,
"initWithFrame:"
);
properties = (
);
}
wannaTestIt is a private method and testValue is a private variable. So I expect that the developer that uses the library can not access them. However, because the user of the library could get the name, the user can ultimately call the method to read the value of the iVar.
How can I prevent this?
If you want to completely "prevent" reflection then, well, you have to use a different language. Reflection is a key thing in Objective C and it's not possible to "block" or "disable" it.
However, you can make this run-time information much less useful for the researcher by obfuscating it. For example, take a look at this tool: https://github.com/Polidea/ios-class-guard. This is just an example. I'm not related to this particular project and you can freely chose a different obfuscator or write your own.
If what you need is to limit reflection to public API only and even disclosing a number of private methods and ivars (without their actual names) is not okay for you then you have no other choice than writing you sensitive code in a different language. You can use Pimpl design pattern to achieve what you want. This way, your classes would only have public methods and a single private ivar _impl (or something like that). Where _impl is an instance of the implementation class that is written in C++ (or Objective C++ if you need access to ObjC APIs) and all public methods act like a proxy. Something like this:
- (NSInteger)computeSuperSensitiveStuffWithFoo:(Foo *)foo Bar:(Bar *)bar {
return _impl->computeStuff(foo, bar);
}
This way all your private data and methods would be encapsulated in the MyClassImpl class. If you keep declaration and implementation of such class in private (i.e. do not distribute MyClassImpl.h file with your library) and use language like C++ for implementing it, then you will achieve what you want.
Also note that if you chose Objective C++ then MyClassImpl should be a C++ class (declared with class keyword) and not Objective C class (declared with #interface/#end block and implemented inside #implementation/#end block). Otherwise all you private data will be available for reflection anyway, but would require a couple of additional steps from the researcher.

Timing issues with swift class with dynamic variable, which inherits from objective c, where the get/set methods are replaced

I have a very specific issue where, if I have a swift class which inherits from an objective-c class, and it has a dynamic property.
Now, on the +initialize, I am injecting getter and setters into the swift(:NSObject) class, and these work no problem, except for a slight issue when setting values from an init overload.
So, my swift class looks like this:
class TestClass: BaseClass {
dynamic var testStringProperty: String?
init(initialValue: String) {
super.init()
self.testStringProperty = initialValue;
// does not trigger the get/set methods
// a po self.testStringProperty will output 'nil'
let xyz = self.testStringProperty;
// xyz is actually set to the value of initialValue, but it does not trigger the getter.
}
}
And the objective-c class that bases the swift is as follows:
static id storedVar;
#implementation BaseClass
+ (void)initialize {
// we are going to exchange getter/setter methods for a property on a SwiftClass, crude but demonstrates the point
if(![[self description] isEqualToString:#"BaseClass"]) {
IMP reader = (IMP)getPropertyIMP;
IMP writer = (IMP)setPropertyIMP;
const char* type = "#";
NSString* propertyName = #"testStringProperty";
IMP oldMethod = class_replaceMethod([self class], NSSelectorFromString(propertyName), reader, [[NSString stringWithFormat:#"%s#:", type] UTF8String]);
NSString* setMethod = [NSString stringWithFormat:#"set%#%#:", [[propertyName substringToIndex:1] uppercaseString], [propertyName substringFromIndex:1]];
oldMethod = class_replaceMethod([self class], NSSelectorFromString(setMethod), writer, [[NSString stringWithFormat:#"v#:%s",type] UTF8String]);
}
}
static id getPropertyIMP(id self, SEL _cmd) {
return storedVar;
}
static void setPropertyIMP(id self, SEL _cmd, id aValue) {
storedVar = aValue;
}
#end
Long story short, whilst in the call to init(initialValue: String), the getters and setters are not triggered, but immediately after the call to init has completed they work.
This is despite the call to initialize completing successfully and the methods being replaced.
But outside of the init function, the get/set behave as expected.
Here is where it get's called.
let test = TestClass(initialValue: "hello");
test.testStringProperty = "hello"
A po test.testStringProperty after the creation of the object, will output nil. But the subsequent assignment, triggers all the correct methods.
It only fails when assigning within the init. Everywhere else it works like a charm.
I would like to get this to work within the initializer if possible, i'm not sure if there is another way to work around it.
Here is a link to the sample app that replicates the issue:
https://www.dropbox.com/s/5jymj581yps799d/swiftTest.zip?dl=0

Without using property how can we access a variable in another class in iOS?

If I want to access a variable that is declared in Class A and I
want to use that variable in Class B .
I don't want to use Property.
How Can I do ?
It is bad practice to declare a public variable without making it a property.
You may also use KVC to access(both read and write) ivar, even if it is readonly.
[instanceOfMyClass valueForKey:#"myIvar"];
I hope someone finds my first stackOverflow answer helpful :)
#interface Class1
{
#public
int var; // if you not declare it public by default it'll be protected
}
// methods...
#end
// Inside a Class2 method:
Class1 *obj = ...;
obj->var = 3;
But property approach is far better.
Well, you can declare variable as public and access it with selector operator, but this is not recommended:
#interface A:NSObject{
#public
int x;
}
#end
...
//Somewhere inside class B
A *a = [[A alloc] init];
a->x;
However it's hard to imagine why it can be better that to use a property.
The 4 possibles cases that I can think to access a variable are:
1 Declare the variable in class A as public
#public
BOOL _test;
Totally not recommended. If you need a public variable you use a property.
2 Use a property.
#property (readonly, getter = myMehtodName) id myVariable;
3 Use a custom method. In practice it acts the same as a property with readonly attribute. Also you can access it with the dot notation.
4 Use KVC to access the variable.
This can be useful when you don't know the name of the property / variable in compilation time.
A little example:
NSString *myKey = [self obtainKey];
id myVariable = [self valueForKey:myKey];
if ([myVariable isKindOfClass:[NSString class]]) {
//Do something
}else {
//Do another thing
}
Note that key can be either a method name or a variable.

How to create private variables in Dart?

I want to create a private variable but I cannot.
Here is my code:
void main() {
var b = new B();
b.testB();
}
class A {
int _private = 0;
testA() {
print('int value: $_private');
_private = 5;
}
}
class B extends A {
String _private;
testB() {
_private = 'Hello';
print('String value: $_private');
testA();
print('String value: $_private');
}
}
When I run this code, I get the following result:
String value: Hello
int value: Hello
Breaking on exception: type 'int' is not a subtype of type 'String' of 'value'.
Also I not get any error or warnings when editing this source code.
How can I create a private variable in Dart?
From Dart documentation:
Unlike Java, Dart doesn’t have the keywords public, protected, and private. If an identifier starts with an underscore _, it’s private to its library.
Libraries not only provide APIs, but are a unit of privacy: identifiers that start with an underscore _ are visible only inside the library.
A few words about libraries:
Every Dart app is a library, even if it doesn’t use a library directive. The import and library directives can help you create a modular and shareable code base.
You may have heard of the part directive, which allows you to split a library into multiple Dart files.
Dart documentation "libraries-and-visibility"
Privacy in Dart exists at the library, rather than the class level.
If you were to put class A into a separate library file (eg, other.dart), such as:
library other;
class A {
int _private = 0;
testA() {
print('int value: $_private'); // 0
_private = 5;
print('int value: $_private'); // 5
}
}
and then import it into your main app, such as:
import 'other.dart';
void main() {
var b = new B();
b.testB();
}
class B extends A {
String _private;
testB() {
_private = 'Hello';
print('String value: $_private'); // Hello
testA();
print('String value: $_private'); // Hello
}
}
You get the expected output:
String value: Hello
int value: 0
int value: 5
String value: Hello
In dart '_' is used before the variable name to declare it as private. Unlike other programming languages, here private doesn't mean it is available only to the class it is in, private means it is accessible in the library it is in and not accessible to other libraries. A library can consists of multiple dart files as well using part and part of. For more information on Dart libraries, check this.
The top answer as of now is definitely correct.
I'll try to go into more detail in this answer.
I'll answer the question, but lead with this: That's just not how Dart is intended to be written, partly because library-private members make it easier to define operators like ==. (Private variables of a second object couldn't be seen for the comparison.)
Now that we've got that out of the way, I'll start out by showing you how it's meant to be done (library-private instead of class-private), and then show you how to make a variable class-private if you still really want that. Here we go.
If one class has no business seeing variables on another class, you might ask yourself whether they really belong in the same library:
//This should be in a separate library from main() for the reason stated in the main method below.
class MyClass {
//Library private variable
int _val = 0;
int get val => _val;
set val(int v) => _val = (v < 0) ? _val : v;
MyClass.fromVal(int val) : _val = val;
}
void main() {
MyClass mc = MyClass.fromVal(1);
mc.val = -1;
print(mc.val); //1
//main() MUST BE IN A SEPARATE LIBRARY TO
//PREVENT MODIFYING THE BACKING FIELDS LIKE:
mc._val = 6;
print(mc.val); //6
}
That should be good. However if you really want private class data:
Though you technically aren't allowed to create private variables, you could emulate it using the following closure technique. (HOWEVER, you should CAREFULLY consider whether you really need it and whether there is a better, more Dart-like way to do what you're trying to accomplish!)
//A "workaround" that you should THINK TWICE before using because:
//1. The syntax is verbose.
//2. Both closure variables and any methods needing to access
// the closure variables must be defined inside a base constructor.
//3. Those methods require typedefs to ensure correct signatures.
typedef int IntGetter();
typedef void IntSetter(int value);
class MyClass {
IntGetter getVal;
IntSetter setVal;
MyClass.base() {
//Closure variable
int _val = 0;
//Methods defined within constructor closure
getVal = ()=>_val;
setVal = (int v) => _val = (v < 0) ? _val : v;
}
factory MyClass.fromVal(int val) {
MyClass result = MyClass.base();
result.setVal(val);
return result;
}
}
void main() {
MyClass mc = MyClass.fromVal(1);
mc.setVal(-1); //Fails
print(mc.getVal());
//On the upside, you can't access _val
//mc._val = 6; //Doesn't compile.
}
So yeah. Just be careful and try to follow the language's best-practices and you should be fine.
EDIT
Apparently there's a new typedef syntax that's preferred for Dart 2. If you're using Dart 2 you should use that. Or, even better, use inline function types.
If you use the second, it will be less verbose, but the other problems remain.

Resources