Protect your project from dependencies (iOS – swift)

The Issue

Here I will talk about some ways I use to protect my projects against changes in its dependencies.
Whats clear is that every library/framework you use in your project would change at some time, and sometimes we change our mind about these dependencies and replace them with others.

Lets first talk about replacing a library. So we have some library that filter an image, lets call it MOImagesFilter, where you provide it an image and what filter you want to use and then it returns the filtered image. Later you find that this library produce a couple of bugs or does not work well with orientation or 3x screen …. And you decide to use a more famous library called e.g. FastImageFilters! and try it.

But wait …

You already imported MOImagesFilter in 10 classes , and in each class there is a couple of lines related to it. FastImageFilters may have totally different APIs and eventually you find yourself updating 30 lines of code !!! Oo

Adapters to the rescue

The idea here is to point all those calls to one class thats more native to our project where you don’t event need to import it in other classes. That class will be responsible to translate the library we intend to use into one formatted language our project understands.

So we create a class lets call it ImageFiltersAdapter that deals only with MOImagesFilter and does what it does , so we don’t have to deal directly with MOImagesFilter directly at all.
We predefine a set of functions that we actually need from the library , we might not need all of the function , in our case we only needs a function where we give it an image with the intended filter and it returns a filtered image.

Later on if we decide to use FastImageFilters we only change in the adapter class , not all the e.g. 3o lines of code and 10 classes.
Another benefit is that we might not need all the functionalities from some library but just a subset.
Also anyone including you when later tries to understand what we are doing here with the filter class will understand easily instead of going to the original library and read through it.

This not only useful when we replace libraries but also when we update a library where its APIs may have changed.

Adding CocoaPod for your library (public/private)

Adding CocoaPod for your library (public/private)

MAC OS, iOS

This post takes you step by step into how to integrate cocoaPods with your library.

CocoaPods is a dependency manager for Swift and Objective-C Cocoa projects

Am going to use an open sourced project I made before on github, and add the cocoapods into it. For you to keep up with me.

  1. Create a repository on github.

You need to Sign up first before you can create new repository. Click on the upper right plus button and choose New Repository. For Reference Lets call it YourPod.

The name should be unique, and make sure to add a license file.

2. Clone the repo

clone the repository for github using their App or through command line

git clone https://github.com/<YourAccountName>/YourPod.git

3. Install Cocoapods

From the terminal type

sudo gem install cocoapods

4. Structure Folders

cd to the folder where you cloned YourPod repository.

Let’s create 2 folders one called YourPod, and the other called Demo.

  • Add your library swift files under YourPod
  • Create an xcode project under Demo Folder
  • Commit Your Changes
  • Push them to github

CREATE THE POD

Before creating the pod. From your repository github page.

  • Click on releases
  • Click on Add release button
  • set the version to be 0.0.1 (this is important, you can set it to any number you want )
  1. Create podspec

From terminal, type

pod spec create YourPod

that will create a podspec file. Open it using xcode or any editor you like.

After you open it, it will look like this ( after removing comments and leaving most of the required attributes)

Pod::Spec.new do |s|
s.name = “YourPod”
s.version = “0.0.1”
s.summary = “A simple HUD to indicate activity, success, and failure.”
s.description = <<-DESC
You can use this Library as a loading indicator while waiting for response from api, you can mention failure and success as well
DESC
s.homepage = “Your project home page "
s.license = { :type => “MIT”, :file => “LICENSE” }
s.author = { “Your Name” => “Your Email” }
s.social_media_url = “http://twitter.com/dark_torch(can be any link)"
s.platform = :ios
s.source = { :git => “https://github.com/YourAccountName/YourPod.git", :tag => s.version.to_s }
s.source_files = “YourPod/*.swift”
s.resources = “YourPod/*.storyboard”, “YourPod/*.xcassets”
s.requires_arc = true
# s.dependency “JSONKit”, “~> 1.4”
end

The license file should be available on the remote repository (e.g. github repo) and belongs to the release you mention in the podspecs file

2. Validate the podspec

From terminal run

pod spec lint YourPod.podspec --verbose

On success you will get “YourPod.podspec passed validation.”, watchout for any warning or error* — verbose is for more detailed logs which should help you if there is any.

3. register the pod in the CocoaPods repo

Now we have our pod validated, we need to push it into cocoapods so others and we can use it. To do that first we need to declare ownership. Simple run this command in terminal from the same directory of the pod.

pod trunk register <YUOREMAIL> ‘<YOUR NAME>’ — description=’owner from macbook pro’

you will get this response

[!] Please verify the session by clicking the link in the verification email that has been sent to <your email>

you should get an email with the validation link within a minute.(It might goes to the spam folder)

4. Upload your pod

Now all we need is to push our pod, simple use this command from terminal.

pod trunk push YourPod.podspec

you should get “ — March 16th, 04:08: Push for `Your pod’ has been pushed (2.792570047 s).” alike message in the terminal.

“if you added your twitter account in the podspec, you will get mentioned in an auto-generated cocoapod new pod tweet ”

TRY IT

Now lets try it

  • Create a Podfile in the same directory where your demo.xcodeproj is.

Your pod may look like this

platform :ios, "8.0"
use_frameworks!
target :Demo do
pod "YOURPOD"
end

if your pod in swift you need to add use_frameworks!

now run

pod install

It will download the pod and create an xcworkspace for you .

Now use demo.xcworkspace , import the pod into your demo and try it.

PRIVATE PODS

you can use a private pod as well although you need few more steps.

  1. Create your own specs repository (where the pod’s podspec file is going to be hosted) (lets call it myspec)
  2. create new folder locally and copy the pod you made before and podspec file.

3. Create new repository for your pod on e.g. bitbucket and upload the files like we did before don’t forget to tag it, you can do it by running

git tag 0.1

and push the tags using

git push -u origin —- tags

4. Add Your specs repository

pod repo add <yourSpecsName> <yourPodRepoDirectory>
e.g.
pod repo add myspec https://bitbucket.org/moath/mospecs

5. Now in your podspec file change the version and source url (it’s better to use https) (Validate as we did before), then push it using >

e.g.

pod repo push myspec MOHUD.podspec — verbose

6. finally in the Podfile add source to refer to your specs repo.

e.g.

source "https://bitbucket.org/moath_torch/mospecs/"
source 'https://github.com/CocoaPods/Specs.git'
##Note: you need to add all resources

Thats should be it .

WRAP UP

Now your Pod should be searchable in https://cocoapods.org/ (if its public)

a nice thing about it is that they will rate your pod based on some metrics like documentation, it worth looking at it and trying to improve your rate.

I hope this helps someone, if you have any comment please add it.

And Thank you for reading.

Links

you can find more detailed info at Cocoapods

Lesson Learnt : UItableView Header always appearing

This is just something I faced tonight

I have a UITableView with PLAIN Style

in the dataSource the sectionNumbers is “1” I swear !!

when I run it into simluator the tableView is shifted down by some 20 pixils !!

The first thing came to my mind is to go and check it on the Interface builder
and from the ‘Size inspector” there is a property called ‘section height ‘ which set by default to ’22’
So yay I just need to change it to 0 and thats it, and thats what I did :
I typed 0 in the field and pressed a BIG Enter problem SOLVED 😀 .. but wait !!!
its not set to 0 !!, instead its 1 …tried again , maybe i just missed the zero the first time !!
but it insists to not to leave the ‘1’ , well ‘I said’ nobody cares about the extra pixil down .
ran it and everything looks OK … or better at least …
my freacking “consciousness” kept tingling me :/ ‘ I need to fix it ,and whyyyyy this happens’

So I took a look at the code and I found that this class is a subclass of another that handle the tableView Delegate ( srsly don’t do alot of subclassing , things may become messy )
SOO I found this code somewhere

-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
    
    UIView *header = [[UIView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 0)];
    
    return  header;
}

mmmmm looks I was trying to add some section header but then I didn’t, but wait !!
ok there is a bad non necessary method here but the ‘height’ is zero and there is no really a header …
although am getting the 22 height empty header on screen !!

srsly I dunno , but deleting this method removed the 1 pixil header … 🙂

OK OK I went to the ducomentation and I read this ( again ‘consciousness’)
This method only works correctly when tableView:heightForHeaderInSection: is also implemented.”
only !! 
so looks if we implemented the ‘viewForHeaderInSection’ no matter what object it returns the ‘section Height’ will be set to 22 as a default value .. unless we implement the  ‘tableView:heightForHeaderInSection: ‘ method WHICH I did not …
but why in the size inpector I couldn’t set it to 0 !!! .. 

Well, I guess it will remain as a mystery .. one little mystery for tonight.. 🙂

P.S. for some reason there is no spelling checker and yeah there will be speeling errorss

Presenting ViewController from UIAlertView (Attempt to present on which is already presenting )

Presenting ViewController from UIAlertView
Something I face this morning which was annoying ,is That I was trying to present a ViewController
After user Tap on a UIAlertView button.
The result was this console log !!
uialertview Warning: Attempt to present <_UIModalItemsPresentingViewController: > on <_UIModalItemAppViewController:  > which is already presenting”
The Code I was using looked like this : 
UIAlertView * alert =[[[UIAlertView alloc] initWithTitle:TITLE
message:MSG
delegate:Dgt
cancelButtonTitle:@“OK”
otherButtonTitles:nil] show];
And in The AlertView Delegate  I called presentViewController
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
    
     MOImageViewController    *_imageVC =[[UIStoryboard storyboardWithName:@”Main” bundle:nilinstantiateViewControllerWithIdentifier:@”imageScreen”];
                    
                    [_imageVC setImageURLString:urlString];
                    
                     
                    // topViewController  
                    [[self topViewController] presentViewController:_imageVC animated:YES completion:Nil];

}
What turned out is that UIAlertView is treated like viewController and upon clicking at one of its Buttons it gets dismissed, So in the previous code am presenting a new viewController while dismissing the AlertView Which gives me the mentioned warning .
The simplest solution for this is simply using another AlertView Delegate which is 
-(void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex{
 // presenting view controller here safely
Thats it 🙂