iOS static library does not work - ios

I followed the instructions in this article to create a static library:
http://developer.apple.com/library/ios/#technotes/iOSStaticLibraries/Articles/creating.html
I built it for iPhone simulator target. It built successfully, then I imported into a new project where I wanted to use it. It imported fine and there are no problems, but the library doesn't work. There are no library methods that I'm calling; rather the purpose of the library is to swizzle the UIViewController viewDidAppear method so that a piece of code gets executed every time a UIViewController appears. This piece of code is not getting called, despite my library being included in the "Link Binary With Libraries" build phase.
I know the problem isn't with the code itself because if I import the raw .m and .h source files not as a library, everything works fine.

Did your library contain any categories?
If so, I think you should follow these steps to get it work:
In Xcode, double-click the target's name under "Targets" in the Project window.
Choose the Build Settings panel.
Scroll down to the "Other Linker Flags" build setting under the Linking collection and set its value to "-all_load -ObjC".
Please refer to corresponding Apple Documentation
Here is a related question: Objective-C categories in static library

Related

How to create SDK for iOS in Swift?

I have my own Xcode project which contains some controllers. I want to make its SDK, for use it in another application. In parent application it works as child. Parent app will share some data with my controller and my controller works on it and gives back some result. So kindly guide for me. Examples are - Payment Gateway SDK's. I am looking for the same.
I can see you add tag for swift. In Swift, static libraries are not supported, so you must exclusively use a framework (aka dynamic library) when linking an app to a library. Framework is similar to sdk.
Here are the steps:
1)Create the Framework using New > Project under IOS > Framework & Library, select Cocoa Touch Framework
2)To avoid the "ld: warning: directory not found for option..." goto Library Search Paths in Build Settings for your target and delete the paths.
3)You can't mix Objective-C with Swift so don't even consider adding the Swift-Header bridge file in your code.
4)There are some cases in swift where you need to import code from unexposed Frameworks. I've successfully used the module-map inside the framework to deal with these case.
5)I also select CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES in the Build Settings to solve 'include of non-modular header inside framework module'. That seems to work
6)I make sure that the header file that gets generated is marked as Public (not Project). Click on the file and you'll see the selection in the inspector under 'Target Membership'
Link
Also you can follow this tutorial. Since you have already created project.
Create a framework target, make all source code files a member of the new target, add the new target as target to the podfile. For everything else the tutorial should work. It should help you in understanding the steps.
Build framework

Don't we need to link framework to XCode project anymore?

Base on this question
Why don't iOS framework dependencies need to be explicitly linked to a static library
I read the selected answer and still don't understand so I made an example project
Test Project on Github
In the test project, I remove all framework from Link Binary With Libraries and File navigation for both main project and the static library (including Foundation.framework and UIKit.framework too), basically, both project link to 0 frameworks.
Questions are
In static library, it's including MapKit/MapKit.h without referencing the Mapkit.framework to the project, why is its still working?
In main project, I remove UIKit.framework and Foundation.framework from the project, why is it still working?
Since it's working for now, will there be any issue later?
Thank you for your comment.
P.S. By working, I mean I can run on the simulator and I can archive the main project without any error.
Edit 25/07/2014
I tried with the real app that I'm working on, it's the same.
I highlight Foundation, UIKit, CoreData and 10 another frameworks in File Navigation, well, all of them.
Uncheck the target in Utilities Panel --> Target Membership
Build : Pass, Run : Pass
Every functionality of my app is still working as expected. I don't get this.
Check your project build settings. Underneath LLVM 5.1 — Language — Modules you should see the option 'Link Frameworks Automatically'. In your case it sounds like it's set to 'YES', the default.
In that case, instead of producing an error when you reference a class that the compiler doesn't know, it'll figure out which Framework contains that class and link it. In your code it'll be MKMapView or one of the other MapKit classes that triggers the linkage.
EDIT: from the relevant 'What's New?' document:
Auto Linking is enabled for frameworks imported by code modules. When
a source file includes a header from a framework that supports
modules, the compiler generates extra information in the object file
to automatically link in that framework. The result is that, in most
cases, you will not need to specify a separate list of the frameworks
to link with your target when you use a framework API that supports
modules.
Another way of looking at it is that the compiler is smart enough to mutate #import to #import when the framework has been built appropriately. All system frameworks have been.
To elaborate #Tommy's answer, a framework that supports modules satisfies the following 2 conditions:
Under Build Settings > Packaging
Define Modules is set to YES
Module Map File exists.
So, if you're certain that the framework you're using in your code modularizes like that, you can choose to not explicitly add it in the link phase as it will be automatically added as long as in the project file, under Apple Clang - Language - Modules, The option Link Frameworks Automatically is set to YES.

Static library in ios

I have created a static library and added it to my project, when i try to debug my application it goes to the .m file of the library. If this library is distributed to some one he will also be able to see code in that library which is blunder, how should i get rid of this.Are there any settings that are to be changed?
If you don't distribute the source file, they cannot see the source file. They may be able to see symbols within the library, such as function or method names, if you don't strip the binary after building it. There is a setting in the "Build Settings" of the project and target settings where you can turn stripping on or off. I believe that it's on for debug and off for release by default.

How to use a static library (e.g. cocoapods library) on a XCTest?

I'm working with Core Data and, as I the model gets more complex, I need to make sure that the new changes I introduce don't break my model unexpectedly in other parts.
I can create unit tests and run them every time I change something on my model. If something breaks, there might be something wrong with my model or at least I know I have to modify some queries in the main code/tests.
I'm using MagicalRecord to have access to some convenience methods.
I also use cocoapods for the same reason, convenience.
The problem is that cocoapods creates a static library and links it against my target, but in Xcode, new test targets are not automatically configured to link against the same libraries/frameworks the target in question links against to.
How can I have a XCTest link against a static library?
This is not only helpful with MagicalRecord/Core Data, but when you're using an external library it's a good idea to have tests to make sure that updates on the library don't break your App.
If you're using cocoapods, you can simply use link_with to include your test target, but if you're using a static library not created by cocoapods you can do the following:
(I will still use a cocoapods library for the instructions, as that's what I'm working with, but the idea is the same if you're not using a cocoapods library)
Once you have created a new Test Target, click on the project root node in the project navigator and select your test target.
Go to Build Settings and search for Header Search Paths. Double click on the Header Search Paths item and enter
${SRCROOT}/Pods/Headers and select recursive if you want to import all of your cocoapods libraries headers or enter them individually:
${SRCROOT}/Pods/Headers/MagicalRecord leaving non-recursive selected (although in this case it doesn't really matter).
Now search for Linking and in Other Linker Flags add -ObjC
Now with your Test Target still selected, go to Build Phases and in Link Binary With Libraries click on the + and add libPods.a or the other libraries individually (libPods-MagicalRecord.a)
You should be able to run a XCTest using the static library.
Optional: I like to import the headers I know I'm going to use in the -Prefix.pch file. You can go to your target test group in the Project Navigator. Go to the Supporting Files group and open the -Prefix.pch file. For MagicalRecord I like to add:
#define MR_SHORTHAND
#import "CoreData+MagicalRecord.h"
For more information:
Unit Testing with Core Data
Creating a Static Library in iOS
Tutorial
After a lot of fighting, these steps worked for me:
1) Project> Info
On configurations, set the Test Target to share the same Configuration File as your main project (generated by Cocoapods).
Now, you should start to get some errors because XCUnit framework is missing, but now your external libraries imported with CocoaPod are visible on your test project.
2) On the Test Target>Build Settings look for Header Search Paths, once there add:
$(DEVELOPER_DIR)/Platforms/iPhoneOS.platform/Developer/Library/Frameworks
$(DEVELOPER_DIR)/Platforms/iPhoneSimulator.platform/Developer/Library/Frameworks
The Unit Test framework is inside your Xcode App, this headers will make them public to be added later.
3) On the Test Target> Build Phases add the SenTestingKit.framework
And it should look like this
From there, everything seems to work for me. Good Luck.

Linker error, but only on test files

Here's a screen capture of my app. I'm using UIKit to create a PDF from some of the app data. I get no errors on the app itself but in the test section I get a bunch of them that look like the app can't find some CoreGraphics references. But CG is being imported in Tests.h... I can run the app, on simulator and device with no problems. Any idea what is causing this?
To add a little more to this: I imported the class where I am making the PDF into another application and I am not getting the errors there, so that's good. So any ideas what could be happening? (And yes, the libraries are in my app)
It is being imported but not linked. You need to link the CoreGraphics framework:
Importing a class header A into class B allows class B to know what public API (variables, properties and methods) in class A can be used by other classes and that is why you do not get any errors until you compile.
When you compile, you need the actual code (.m file if you will) to be able to execute the calls that class B is doing to class A variables, properties and methods. That code resides in the libraries/ frameworks you link to your project. Your code with the linked libraries together become the final compiled code.
Here is what you need to do:
Single click on your project (top left of the navigator)
Select your Target project
Click on the "Build Phases" tab
Click on "Link Binary with Libraries"
Add CoreGraphics.framework
That should solve it.
I solved it. I removed the libraries, reinstalled them and did a clean and that seemed to fix the issue.

Resources