multiple UIImage+ImageEffects files in one project - ios

I have a couple third-party libraries (not using cocoapods) in my iOS project, and when I dug into the files of each, I discovered that 4 of these libraries had their own versions of the UIImage+ImageEffects category. So I was about to merge them into one single file, but that got kind of messy:
For instance, one of the libraries, SCLAlertView, has a custom method inside its version of UIImage+ImageEffects which refers back to one of SCLAlertView's classes to access a variable. So if I import that class into the merged file, It would make the new UIImage+ImageEffects dependent on SCLAlertView. I dont feel comfortable about that, and its not pretty. So I need your guys thoughts on this :
What is the best approach to go about this? Should I just go ahead and merge them or keep them as separate files in their respective libraries?
Does having multiple, slightly different, versions of the same category in a project really matter? does it give rise to any issues/conflicts?
i often see this :
Class _NSZombie_OS_dispatch_group is implemented in both ?? and ?? ...
in my console. is this by any chance caused by the above thing?
Thanks in advance.
Note: I didnt give the question a generalized name like "multiple versions of same category in one project" because UIImage+ImageEffects is used by lots of libraries for blur effects and has the most chance of ending up as multiple slightly different versions in your project

Answering 2 will drive the answer to 1 (and 3 sounds like a bug in the system, you should file it :) ):
Does having multiple, slightly different, versions of the same category in a project really matter? does it give rise to any issues/conflicts?
As long as all method names are unique, there isn't a problem outside of the issue that categories on system classes are awful for the long term maintainability of a codebase.
If, however, the categories all have methods of the same name -- which they likely do -- then only one of them will be used and which one is indeterminate.
Thus, yes, you'll need to merge them. Or, better yet, eliminate them entirely by refactoring them into a helper class or something (then file a bug against the original codebase and have 'em pull the changes).

If you build and integrate your 3rd party libs as static libraries, every lib is isolated and uses its own version of the category, and things should work fine. In this case, you should keep the categories internal to the libs and avoid exposing them by means of #include in public headers. EDIT: As pointed out by bbum, category methods are not isolated inside their containing static lib; wrapping the libraries as static libs would not solve the OP's problem.
If you just have one build target and integrate the libs by source, things will work OK as long as the duplicate method implementations don't differ (even though this might result in lots of linker warnings).
Issue will arise if the category implementations differ, because the resulting behavior (i.e. which category method is used at runtime) is undefined (see this post). In this case, I don't know a good solution for the problem; a not good (but working) solution would be to rename (prefix) the methods in each lib's category and use the renamed method in the respective lib. E.g. in lib A, you would rename imageByApplyingLightEffectToImage: to a_imageByApplyingLightEffectToImage: and change all calls to that method inside A accordingly. As I said, I would use this approach as a last resort only.

Related

Create Framework / Library / Module of Swift Objects in Xcode

I am a (very) novice iOS/Swift programmer with a basic question about moving reusable software objects to their own ... something.
I am developing three iPhone apps that present information from three distinct data sets. Those data sets contain unique information but are structurally similar. As such, the apps share some Swift classes that are identical, specifically the classes that model the data. As I continually refactor the code, I find that when I tweak a class in one app's project, I have to remember to go to the other two projects and make the same tweaks to the same classes for those apps. It's getting to be a big headache.
What I would like to do is have one class definition in its own ... something that I can share, link, import, or attach to/from each app's project. From my online research, I suspect that the ... something is a library? or maybe it's a framework? or a module? I have found all three terms are used, but I am not sure how they relate to each other.
Given that all of the software I am writing is in Swift, does Xcode support what I am trying to do? Thank you!
It seems you have the issue of needing the same Swift class in multiple projects. You could build a Framework (aka Module) for this class then copy it in to each project. This is probably the formally correct approach but it is a bit of overkill for just a single class.
Instead, you could just make the file in the Navigator panel a reference in each project to the one actual file.
You could also make a Workspace and then put each project into the workspace and just have the file at the top level (but this may introduce some build complexity).

How to share common classes with extension with many dependencies in a smooth way?

Im currently working on a iOS project where we now want to add some feature for the Apple Watch. Since the extension for Apple Watch is a different target I naturally can't access the code written for the App. I have searched here on stackoverflow and have found two different ways to solve this problem.
Create a dynamic frameworks. This would definitely be the best approach but unfortunately the app must support down to iOS 6, and what I have found this solution will only work on iOS 8+.
Link the files in either Build Phases -> Compile Sources or through Target Membership in File Inspector. The main problem here is that the two classes we want to use have many dependencies to many other classes, which also have other dependencies and so on. From what I understand I need to include all these other files as well if I want to make use of the classes I intend to use in the extension.
So my question is if there is any other better way for me to accomplish this. If I choose #2, first of all I need to include all files, and after that, from a maintenance point of view, if I make changes to there files, for example importing an other class, I need to include that one as well in Compile Sources / Target Membership. Would really appreciate any ideas or advice regarding this! Thank you!
I don't know how "deep" is your coupling regarding point 2. However if you can use interfaces(protocols) instead of direct class referencing you can separate just the classes you need.
Moreover you could re-think whether specific class really need some other class to operate(probably not) or just some methods from it. Those methods could be moved to protocol and your dependant class to implement it(now this class do not need to be part of AppWatch target).
This will be heavy work though if your project is really big and your classes are tightly coupled. I would advice you to read this article about Dependency Injection and especially 'Dependency is bigger than Testing part' :)

How to find unused properties for iOS class?

I cannot find any similar questions on this topic, which seems strange..
I have what is turning out to be a rather large project. As I build each chunk, I'm aware that I must be making properties and other resources, that do not end up being used.
Is there a way to find these?
Good question. I always need this too in my projects. What I do is either use search for .property or setProperty etc. in the whole project.
Or I traverse the .h files and comment out the property declarations that I suspect I might not be using and hit Command+b and see if it gives any errors.
I hope there is a function/tool specifically built for this need.

Do I really need to create an iOS static library for internal-use-only code?

In a brainstorming meeting, someone recommended that we use a static library in a future project. I have researched this topic all day.
I have found some helpful answers about what a static library is and how to create one.
Library? Static? Dynamic? Or Framework? Project inside another project
I've also found answers on how to use resources with a library:
iOS Library With Resources
My Question Is:
Do I really need to create a static library, or should I just create a class for internal-use-only code?
Conditions:
I have three projects that require a special encode and decode engine.
The engine's functions involve cryptography, IP packet transport, and hardware binary coding.
There are fewer than 20 functions.
We will never release this engine to a third party developer or open source it.
Another way to ask:
In what circumstances should I create a static library?
Even if you don't want to share your code with other developers, you can still gain tremendous benefits from creating a static library.
As Srikar Appal mentions, benefits gained from creating a static library are 1) Code Distribution, 2) Code Reuse, and I'd also like to add, 3) Versioning, 4) Testability (kudos to BergQuester's comments below) and 5) Documentation.
Let's look at these more closely:
1) Code Distribution
Static libraries are great because they make it easy to distribute your code- all you have to do is compile and share the resulting .a file.
Even if you never plan to share your code with other developers, you can still make use of this across your own projects.
Alternatively, you might instead include the static library's project as a subproject to your various main projects, making this a dependency of the main project... see https://github.com/jverkoey/iOS-Framework for how this can be setup.
2) Code Reuse
Even in very different apps, you'll often find that you're doing the same task that you'd previously written code for. If you're an efficient developer, you wouldn't want to write the same code again... instead, you'd want to just include your previously written, polished code.
You might say, But I can just include the classes directly.
What if your code isn't necessarily polished, however? Or as tends to happen, the frameworks it uses change over time?
As you make changes and bug fixes to the code set, it'd be nice to be able to easily include the latest version in your projects (or be able to easily update your projects later on). A static library makes this easier to do because all the related code is included within a single package.
There's also no worrying about what other project-specific hacks other developers have been imposed on it - the main project can't (or in the case of a static library included as a subproject, shouldn't) change the static library's code set.
This has the added benefit that if someone does need to change the static library's code set, he must make the change such that all projects relying on it will still be able to use it (no project-specific shortcut hacks).
3) Versioning
If you have a set of classes that are moved around and included project to project, it's hard to keep up with versioning. Most likely, the only versioning you do have is that of the main project.
What if one project fixes some bugs and another project fixes other bugs within this class set? You might not know to merge these changes (what if two teams are working separately even on these)? Or, each project might be fixing the same bugs!
By creating a static library, you can keep track of versioning (the static library's project has its own version number), and by making changes on the static library, you'll have less merge issues and eliminate the risk of fixing the same bugs over and over.
4) Testability
As iOS continues to mature as a platform, unit testing your code is becoming more and more prevalent. Apple even continues to build and expand on testing frameworks (XCTest) to make it easier and faster for iOS developers to write unit tests.
While you could (and, IMHO, should) write unit tests for your code at the application level, creating and encapsulating code withIN static libraries typically makes these tests better and easier to maintain.
The tests are better because well-designed static libraries encapsulate purposeful functionality (i.e. a well-designed library performs a specific task, such as networking tasks for example), which makes it easier to "unit" test the code.
That is, a well-designed static library sets out to accomplish a predefined "purpose", so essentially, it creates test boundaries naturally (i.e. networking and presenting the fetched data would likely be at least two separate libraries).
The tests are easier to maintain because they would be within the same repository (e.g. Git repo) as the static library code (and thereby, versioned and updated alongside this code). Just like you don't really want to copy and paste code from project to project, you similarly don't want to copy and paste tests, either.
5) Documentation
Like unit testing, in-line documentation continues to become more important in iOS.
While you can (and again, IMHO, should) document code at the application level, it's again better and easier to maintain if it's at the static library level (for the same reasoning as unit testing above).
So to answer your question,
Do I really need to create a static library, or should I just create a class for internal-use-only code?
You might ask yourself the following:
Will this code be used across multiple apps?
Will this code ever have more than one class?
Will multiple developers be working on or using this code concurrently (possibly in different apps)?
Will this code be unit tested?
Will this code be documented?
If you answer YES to most of the above, you should probably create a static library for this code. It will likely save you trouble in the long run.
If you answer NO to most of the above, you might not gain much benefit from creating a static library (as the code set would have to be very specific to a project in such an instance).
In my opinion creating a static library has the following benefits -
Code distribution - This is the biggest reason (perhaps the only reason) developers create a static library. It obfuscates the actual code and exposes the API methods. But since you have explicitly mentioned that this "library package" would never be distributed to 3rd party developers this reason might not apply.
Code Reuse - This is the other reason I can think of. But then, one can achieve code reuse by simply using classes in (.m files), having the method definitions in header file & importing the header file (.h files). So this is not much of a reason to create a static library.
I am not aware of any performance benefits due to statically linked code. Also creating static library has its own maintenance overhead. It would not be as simple as creating one build. You would have to keep in mind linking the static library, maintaining compatibility etc.
So in your case creating a static library might not make much sense.

Include libraries in iOS library project

I am writing an iOS library which depends on some other open-source libraries. Apparently it is not possible to have two classes with the same name, so it is possible that the library compiles, and a project that potentially could use it compiles as well, but they do not work well together (at the linking phase).
The library is targeted at a large audience, so I can not make any assumptions on whether these developers will be importing the same libraries or not, or if they might be using a different, incompatible version of the same libraries.
I have been looking around but couldn't find any clear solution to my problem (maybe there isn't). So far I am thinking of these options:
Inform the users that X libraries are already included in the project, so they do not include them as well. This means they can not use a different version of X libraries.
As a refined version of the first one, use CocoaPods, so dependencies are resolved automatically. Still has the disadvantage that two versions of the library can not coexist.
Import and rename all classes my library depends on, prefixing them, so the names don't conflict with the original ones. This is tedious work, but more importantly, has the disadvantage that I would not be able to pull/push code from/to the original library, as the code would change too much. Still seems to me the best option from the user perspective.
Can you think of a better idea? I'm pretty new to library projects, so maybe there is something obvious I am missing.
We're still not decided whether to distribute in binary or source code form. If there is a reason to choose one or another I would also like to hear your opinion.
When I was faced with this problem I choose your third option and prefixed the dependent classes within my library. The reason you might want to consider doing this rather than relying on the user to import the others would be that you can guarantee compatibility and you don't have to worry about versions of who you depend on.
First point -
Inform the users that X libraries are already included in the project,
so they do not include them as well
so you have a static library Foolib.a, it has a 3rd party dependency Barlib.a, in order for Foolib to build, Foolib's HEADER_SEARCH_PATHS must be set to the path of Barlib's public headers. No more.
If you are distributing your source code you can use CocoaPods (this is a good way to go), or you can add Barlib's repository as a git submodule (or whatever for your choice of VCS) of your repository and hard code the HEADER_SEARCH_PATHS to that path, or you can require that your user grabs their own Barlib and manually edits HEADER_SEARCH_PATHS to the correct path (if you go the CocoaPods or submodule route the user can easily do this as well, so has more options).
Nothing from Barlib is 'in' your project.
On the other hand, if you are distributing a binary for your user to link into their app you must specify in your instructions that Foolib requires Barlib to be linked into the app. Instructions for how to get hold of Barlib would be nice.
Nothing from Barlib is 'in' your project or compiled into your library.
Second Point -
use CocoaPods, so dependencies are resolved automatically. Still has
the disadvantage that two versions of the library can not coexist
Two versions of the same library in one App is impossible, but the situation where the end user already requires Barlib 3.0, wants to use your Foolib, but Foolib requires Barlib 4.0 doesn't have to ever arise - It is up to you the developer. You can be generous and support multiple versions of Barlib (i.e. all Foolib needs to work is a Barlib1.0, Barlib2.0, Barlib3.0 OR Barlib4.0 linked into the app - similar to writing an app that supports iOS5 and iOS6) or, you can be opinionated and require a specific version, and if the user is already requiring a different version of Barlib, tough luck, they will have to change their code if they want to use your library.
Third point -
Import and rename all classes my library depends on, prefixing them,
so the names don't conflict with the original one
This is just too terrible for me to consider at the moment. Sorry.
Nothing from Barlib is ever 'in' your project or compiled into your library. You don't distribute any copy of Barlib - either linked into your binary or as source code.

Resources