Get Which iOS Frameworks are Available? - ios

I'm writing a static library for iOS. I want to programmatically figure out if CoreLocation is added to the project, is there any way to do that?

Probably something like:
if(NSClassFromString(#"CLLocationManager"))
{
NSLog(#"CoreLocation is available");
}
Would do it. NSClassFromString takes an NSString and checks whether there's a class of that name currently available in the runtime. If so then it returns the Class object, otherwise it returns nil. The if statement there effectively compares to nil.
So, the logic you're applying is "does a class called CLLocationManager currently exist?", which is a proxy for checking that CoreLocation is loaded because it's one of the fundamental classes to that framework.

Related

EXC_BAD_ACCESS when extending CLPlacemark -- variable accessed outside definition scope

I have an issue that I've figured out how to fix but I want to understand why it doesn't work -- because it makes no sense to me. Here's a minimal example that demonstrates my issue:
import XCTest
import CoreLocation
class ExampleTests: XCTestCase {
var okay: ext!
// this test works fine
func testOkay(){
okay = ext()
XCTAssertNotNil(okay)
}
// this test crashes with EXC_BAD_ACCESS(code=1, address=0x10)
func testNotOkay(){
let notOkay: ext
notOkay = ext()
XCTAssertNotNil(notOkay)
}
}
extension ExampleTests {
class ext : CLPlacemark{
}
}
I'm following a book to develop a simple TodoList application that uses CoreLocation to geocode addresses. As part of testing, I had to create a mock CLPlacemark object to test the geocoding functionality.
In the book, I was told I had to declare a variable for this mock as a property of the Test class because otherwise "the test would crash since the place mark is accessed outside of its definition scope."
This can be seen in the example above. testOkay() works fine because okay was declared as a class property. testNotOkay() crashes with an EXC_BAD_ACCESS error, because I've tried to instantiate a new instance of ext within the function.
Now, if I do not extend CLPlacemark, the problem goes away -- i.e. I can declare variables of type ext in a function or as a property of the class with no issues.
What is going on here? I see no reason why the second example should crash while the first one works. In my actual code, it seems frivolous to declare my mock placemark instances as class properties when they're only used in one or two functions. There must be something I don't understand about Swift that is causing this problem.
Thanks!!
I recently run into this issue when testing feature which required providing predefined CLPlacemark instances as an input. After some research I found that someone had similar problem with CLBeacon class.
EXC_BAD_ACCESS when setting a CLBeacon to nil
Placemark objects are typically generated by a CLGeocoder object, although you can also create them explicitly yourself.
Despite Apple documentation saying that you can create CLPlacemark instances by yourself. This class is not a nice guy when it comes to subclassing. It depends on a private class called CLPlacemarkInternal which is nil when you create an instance. On the image below you can see how this object looks in debugger. The _internal ivar has value of 0x0 which is nil.
Crash with EXC_BAD_ACCESS message occurs when the object you instantiated gets deallocated. Regardless whether you go out of scope or assign another object (or nil) to the variable. Why is it happening? This is a question to Apple developers. But below you can find some workarounds other people implemented.
http://szulctomasz.com/2015/07/01/ios-unit-testing-in-swift-and-clplacemark-mocking.html
Extending CLPlacemark results in EXC BAD ACCESS
I have also experienced the exact same issue.
I resorted to subclassing MKPlacemark instead.
This finally allowed me to set the desired mock properties I needed to get my test to past

When to use respondsToSelector vs objc_getClass

if respondsToSelector("UIAlertController"){
//do something
}
if objc_getClass("UIAlertController") != nil{
//do something
}
These both have the same results overall. Is there a case when one is better than the other one? Or should only one of them be used and the other forgotten?
respondsToSelector : This is basically used for to check if object reference, can call perticular method or not. For example, object has inherited from some base class or implemented by some protocols, then it is better to check whether object is able to respond to that method or not, then only call it.
Otherwise it will throw runtime error, method not found type.
if([obj respondsToSelector:#selector(anyMethod)]) {
[obj fizzyWizzle];
}
else {
// do something
}
objc_getClass : The Class object for the named class, or nil if the class is not registered with the Objective-C runtime. It means, are you able to access this class or not, if that class does not exist then it will return 'nil'. So,
if objc_getClass("UIAlertController") != nil{
// it means, these class is available in SDK, hence its iOS version is 8.x
// here you can alloc - init and use UIAlertController functionality
}
else {
// class could not be found
// iOS version is < 8.0
// here that class is not available hence use UIAlertView which is supported by iOS 7 and earlier.
}
Hope this helps.
For checking the class existence you must use objc_getClass. (For Class compatibility with iOS versions)
For checking whether a class implemented a method or a method is available or not you need to use respondsToSelector (For method availability with versions)
These two methods do not have the same result overall.
Responds to Selector
The first case respondsToSelector is a part of the NSObject protocol and will simply indicate if an object is capable of responding to a message with the given signature, at the time of calling. It can be used for a number of cases:
Polymorphism. Ie, informal protocols, or particularly in conjunction with conformsToProtocol for checking if an instance (of any class) responds to the part of a protocol under the #optional directive.
For deciding whether to forward a message to another target.
For instrumenting an object with additional functionality at runtime, for example putting transaction/rollback capability on a persistent model object.
In publish/subscribe type scenarios.
Get Class
The second method is a low-level member of the Objective-C runtime. It is used to simply check the kind of class an object is presenting itself as. (It will check the isa pointer). There are methods on the NSObject protocol that can do the same thing, and it would be generally recommended to use these, unless you have a specific reason to fall back to the lower level APIs. These methods are [an instance class] and [anInstance isKindOfClass].
Replace instanceof with Polymorphism
While there are a great deal of valid uses for querying an object's class, in a typical application it is often a design flaw. There's a refactoring pattern called "replace instanceof with polymorphism". By that we mean, instead of asking an object what kind of class it is, then doing something, instead specific based on that, instead create a protocol and have each of the possible classes implement the method of that protocol in their specific way. Example:
if ([foo isKindOfClass:[Holiday class]]) {
//evaluate if approved
} else if ([foo isKindOfClass:[SickLeave class]]) {
//evaluate if approved
}
Instead do . .
id<Leave> leave;
[leave approveOrDecline]

iOS / Objective-C: Correct Way of Obtaining Meta Class Object

Which from the following is the correct way of obtaining the meta class?
Class myMetaClass = objc_getMetaClass("NSString");
Or:
Class myMetaClass = object_getClass([NSString class]);
Are they both any different?
As mentioned in another post that is linked by the first answerer here:
Please tell me why objc_getMetaClass(); would break in certain cases in detail.
The proper way to use those in different scenarios.
Both functions are correct, but objc_getMetaClass("NSString") only works if NSString is registered with the objective C runtime. Which it almost always is if you want to get its metaclass.
But if you're creating a class using Class myClass = objc_allocateClassPair(superClass,"my_own_class",0) the situation is slightly different.
my_own_class isn't registered yet, so if you need to access the metaclass (in order to add class methods), you must use object_getClass(myClass).
objc_getMetaClass("my_own_class") would return nil.
The difference is, that the second function returns the object for the named class and the second first the object for the metaclass of the named class... :)
Both of them call the class handler callback if the class is not registered to check a second time. When you call the metaclass function you WILL get a return result.
...(However, every class definition must have a valid metaclass
definition, and so the metaclass definition is always returned,
whether it’s valid or not.)
from: Objective-C Runtime Reference
I think your real question is: What is the difference between a class and a metaclass ?
Please have a look at this excellent explanation:
What is meta-class in objective-c

iOS / Objective-C Meta Class and Category

I understand a class is actually an object / typedef of struct (objc_class*).
Each class has a "backing" meta class, which in turns has a isa pointer pointing to the meta class of NSObject.
And NSObjectbasically has a isa pointer pointing back to itself.
And we could get a hold of the meta class via this line:
objc_getMetaClass("<CLASS_NAME>");
I hope my understanding of meta class is not off here so far (please correct me if it is).
My questions are:
1.)
When would we need to deal with meta class? Could you please cite an
example / a scenario in code when we might need to?
2.)
Background:
I was thinking freely about third party libraries and how they are structured.
Usually they provide you with a class method and return you a class and all other methods are private / "hidden". And most of the time, while they can be subclassed but since we do not know the init method, it would be of no use to subclass.
And suddenly I began thinking about Objective-C Category and thus leading me to think of Objective-C meta class.
And this leads to my question #2:
Is it possible to break this structure by making use of Objective-C
Category and / or with the use of meta class (by grabbing a hold of
it and insert a class method straight there in the meta class)? Or
even look up the name of their instance methods that are private?
My intention here is not to "break" anything, I am just very curious as to how "unbreakable" these third party libraries are structured and if their structures cannot be "broken" via the use of Category and Meta Class.
#Leo Natan:
1.)
What is method_*()?
2.)
For the love of Objective-C Runtime:
Could you cite an example implementation-swizzling an instance method, let say,
(I am not sure if this method is a good example, for we could override it in the first place)
NSArray's -count instance method (let’s make it so that it returns always count 100, for example)
3.)
So in theory all classes (including all third party libraries) can be break (broken)? Other words, there is no way to create a „call-only-this-class-method-or-you-cannot-use-me“ API / library?
Thanks a lot.
The meta class is useful when wishing to view, add or modify class methods and class-level information.
For example,
IMP myIMP = imp_implementationWithBlock(^(id _self, NSString *string) {
NSLog(#"Hello %#", string);
});
Class cls = objc_getMetaClass("NSString");
class_addMethod(cls, #selector(test:), myIMP, "v#:#");
[NSString test:#"lala"];
To get instance methods, you use class_copyMethodList() on the class returned by class method on an object or NSClassFromString(). You will get an array of all the instance methods defined by the class (but not of its superclass!). You can then use the various method_*() methods to retrieve information and possibly even modify these methods (like implementation swizzling).
You can call class_copyMethodList() on the meta class to get all the class methods defined.
To address your "Leo" questions,
1.
Please read the Objective C Runtime Reference. You can find a section of method_ functions dealing with Method structs.
2.
See tutorial on implementation swizzling.
3.
Using Objective C, everything is available to the runtime. It goes without saying, that with great power comes great responsibility. The Objective C runtime is very powerful. These swizzles are very dangerous and usually not recommended.

what does do method class in objective c

This might be a silly question. I'm learning objective C (iOS) by studying the code and I came across the expression
[InstanceName class];
What does it do?
I tried to search for class method but It just pops up difference between class method and instance method etc. I guess it might give some sort of class object but I have no idea what is the purpose of the statement.
the original code is Sample Facebook App (scrumptious) using FB SDK....
If you see something like this as a standalone expression....
[InstanceName class];
... then the code is most likely forcing the execution of the +initialize method on said class. The first time any method is invoked on a class, the +initialize method will be invoked prior by the runtime. So, have a look at InstanceName and see if it has a +initialize method.
Note that forcing +initialize to execute in this fashion is a sure sign of bad design. +initialize should never need to be forced like this and should not have execution order dependencies.
There is a legitimate additional reason why this line of code might exist. By referring to InstanceName with a hard reference, it'll force the linker to link in all symbols in the library. (If you don't have a hard reference to at least one symbol in a library -- a .a -- some linkers will simply drop the library from the link unit entirely.)
It gets the class of the object.
So for instance if InstanceName is an instance of class Foo
[InstanceName class]; will return Foo, in a variable of type Class
You can use class_getClassName to get an NSString from this class to log it.
class is a method inherited from NSObject. It lets you get the instance of the class object representing the class of the instance on which the method is called.
It can be used to examine the metadata of the current object. For example, you can use class method to determine if a given object is of a particular class:
if ([sender isKindOfClass:[UIButton class]]) {
...
}
It returns the class of the object. Suppose you have an array of UIView subclasses you created and you want to perform some action only to those who belong to a certain class. You could loop through the array and check for each object's class:
for (id view in myViews) {
if ([view isKindOfClass:[MyUIViewSubclass class]]) {
// Do something
}
}

Resources