Distributing Enterprise iOS App in-house (without MDM)


Provisioning and distributing iOS app in-house using enterprise program is quite complicate and most of the times gets overwhelmed. Recently I published an app in-house for enterprise account successfully after facing initial challenges and going thru lot of Stackoverflow Q&A. Preparing this tutorial for future reference and for anyone who want to use it for their own enterprise in-house app distribution setup.

Enterprise iOS app can be distributed using MDM service also but also comes with additional cost. Below approach is without MDM service and can be hosted on cloud storage hosting services like Google Could storage.


Pre-requisite:

  1. Apple Developer Enterprise Program account — It’s $299 per year
  2. Native iOS App
  3. Self host secure (https) server — Alternatively, you can have Google Drive, Dropbox, Google cloud storage or similar storage services account

Process to distribute enterprise iOS app in-house:

Create iOS Distribution Certificate: This needs to be done using your Apple Developer Enterprise account as below and follow on screen steps.

Create App ID: Created App ID will be used in next step.

Create iOS Provisioning profile: Select In House as distribution method and during next step select the App ID created in previous step. In the last step download the provisioning profile and double click it to implement it.

Select manually Signing certificate: By default, Signing is selected as “Automatically manage signing”, uncheck the box and select provisioning profile created in earlier step and select Enterprise account Team. Signing certificate will show your certificate created in step # 1. Follow same for debug and release.

Select Code Signing Identity under Build Setting as iPhone Distribution for enterprise account

Create Archive (Product -> Archive)

Once Archive is created, select Export option and select Enterprise as method of distribution

Follow onscreen instruction and Select newly created distribution certificate and profile

Provide location of URL where app IPA, Manifest file and display images will be stored. Remember it needs to be https address.

Once you follow on screen instruction, it creates the App folder which you can store on your mac. Upload the .ipa & .plist file to https server mentioned above.

Upload the 57 X 57 and 512 X 512 images to the server as mentioned above.

Metadata (MIME) for .ipa needs to be application/octet-stream and .plist needs to be text/html

Create html file with below content and upload same location as like your .ipa, etc. It can be at any other https location also.

<html>
<body>
<a href=”itms-services://?action=download-manifest&url=https://storage.googleapis.com/data/iOS/appName.plist“>
Install iOS in-house App</a>
</body>
</html>

Make sure your .ipa, .plist, images and html can be accessed by your desired audience.

You can share the html link to your users and they would be able to download the app by clicking “Install iOS in-house App” on your html.

After downloading the app, users needs to Trust the certificate under Settings → General → Device Management → <Enterprise Name> then only they would be able to open the app.

Feel free to comment below for any questions.

One of the best feature of iOS11


Finally iOS 11 is public and There are few great features in iOS 11. The one I liked most is automatically turning on DO NOT DISTURB mode while driving. It turns off notifications and work just like do not disturb mode. With location changes, it automatically identifies if it’s in driving mode or not and turn on the feature automatically. As soon as car is parked, DND turns off.

Great feature, hope many people use it and avoid careless accidents on the road.

Why I moved back to Technology?


Since I moved from project management / business role to iOS Developer, many people has asked why you did the change and how did you do? So here is why I did change my career track from management to core technology. I’ll have another detailed blog about how I did the change.

I’m working in IT field over 11 years now and with great performance comes the move in the career. As I kept performing well and completing the assigned responsibilities to the best of my abilities, I was moving up the ladder and getting new additional responsibilities. Initially with people management, managing project work and later moving into full time project management roles as project manager, scrum master etc. Even I did PMP and CSM certifications. I’m someone who is always ready to learn new things, and working on challenging work.

On regular basis, I do couple of things.

  1. Learning new things and upgrading existing things I already know
  2. Self assessment of career and skill sets

While I was moving towards management track and performing project management roles, I was not able to enjoy what I was doing fully. My interest was more towards the technology and building something people can use. That’s where I started thinking about different scenario’s. I looked myself after 5 years performing roles which comes on the way in management and technology, and which one I would love to work 16 hours a day if required. It was clear, I would be much happier with technology track.

As I decided I want to stay in technical role in long term and build some cool stuffs, I started long journey back to technical with re-skilling and up-skilling existing technical experience. My previous background in technical roles and computer science background helped me to quickly learn required technical skills to be a developer again. I self learned iOS Development starting in Objective-C and moving to Swift as soon as it came in 2014. Along the way, I learned Android development too and became iOS Developer with knowledge about entire mobile app development platform. I spent many late nights and weekends to learn the skill set. During the learning phase, I spent many hours building practical apps and launched multiple iOS and android apps which included complex functionalities, usage of API’s, third party libraries. Studied hundred of apps for their design, functionality, flow of the actions, what could be improved and sometime creating duplicate of those apps on my own. This gave me great experience of building and working as iOS Developer.

With practical experience of building apps on my side projects and launching multiple apps on the app store used by thousand of the users, I moved into full time iOS mobile app development. That brought me back to fully technical role. It’s always evolving field and learning new technology and building some cool useful product is the key.

Also, Both management as well as technical track has it’s own advantages & disadvantages, it’s up to individual interest and long term goals in life. My interest is towards technology so I moved back to technical role and will be continuing to learning new technology.

How to build secure iOS App avoid breach by Reverse engineering


In today’s world customer trust is at most required for any app to be successful. To gain the customer trust its most important to build secure app which take care of data privacy and store customer data securely. Customer data can be secured by adding inbuilt data protection and not storing customer private data on device without encryption. Here are few steps which can provide data security for iOS app.

  • Using XCode inbuilt capability of data protection to store the sensitive data on the device so data will be encrypted format
  • Use secure and if required multi-authentication login flow
  • Not storing sensitive data locally on device unless it’s encrypted
  • Use secure authentication (https) for accessing data from network
  • Use trusted and well established backend systems (AWS, Firebase, etc) for storing data remotely
    15855489588_6c209780a9_b

Also, apart from customer data, it’s very important to protect apps from reverse engineering. Hackers, competitors or anyone can learn a lot of things about the app by doing reverse engineering the public binary of the app (App on the app store). With just few steps and little technical background, anyone can access what frameworks used in the app, images and publicly stored files. But as app developer, no need to worry about this as most of these details are already publicly available be in on the app store or frameworks used by millions of other apps. The thing which needs to be concerned is, reverse engineering of the app, shouldn’t lead to accessing intellectual property (IP), architecture of the app, design flows and source code. There is high risk of hacking / reverse engineering the app which are running on jailbroken devices compared to non-jailbroken devices. Through code injection, traffic monitoring, IPA decoding, hacker has ability to access the code. Below are few things which can avoid unintended access by reverse engineering the app.

  • Check for jailbroken devices and close the app by wiping out sensitive data from the device.
  • Do string obfuscation
  • There are some third-party API’s which can be used to protect app from reverse engineering, hacking and malpractices. Like EnsureIT from Arxan

In conclusion, There is always danger of access app by unintended users so it’s architect/developer responsibility to build the app as much secure as possible.

Higher Order Function in Swift 3.0


 

Keep it Simple

Swift has made programming lean and clean. Higher Order functions certainly makes writing complex tasks on collection types much easier and simple. This can be very good replacement for many “for” loops. Here are the four higher order functions which should be used on collection types regularly to write swift code.

  1. Map: Map loops over the collection and applies the same operation to each element in the collection. 

    Let’s say, you want to have square of the items in the array called numberArray. Here is how we can do using “for” loop.

    var numberArray = [1,3,7,10,12]
    var squareArray: [Int] = []
    for number in numberArray{
        squareArray.append(number * number)
    }
    print(squareArray)
    // squareArray = [1, 9, 49, 100, 144]

    Alternatively, it can be done simpler way using Map on array as below:

    var numberArray = [1,3,7,10,12]
    let squareArray = numberArray.map { $0 * $0 }
    print(squareArray)
    // squareArray = [1, 9, 49, 100, 144]
  2. Filter: Loops over the collection and return an array that contains elements that meet condition.

    Let’s say, you want to filter even numbers only in the following array example. square of the items in the array called numberArray.Here is how we can do using “for” loop.

    var numberArray = [1,2,3,4,5,6,7,10,12,14]
    var evenArray: [Int] = []
    for number in numberArray{
        if (number % 2 == 0){
            evenArray.append(number)
        }
    }
    print(evenArray)
    // evenArray = [2, 4, 6, 10, 12, 14]

    Alternatively, it can be done simpler way using filter on array as below:

    var numberArray = [1,2,3,4,5,6,7,10,12,14]
    let evenArray = numberArray.filter{ $0 % 2 == 0}
    print(evenArray)
    // evenArray = [2, 4, 6, 10, 12, 14]
  3. Reduce: It combines all the items in the collection to create a single value. 

    Let’s take example of string instead of integer this time. Say, you want to combine strings in below array. Here is how it’s done using for loop.

    var stringArray = ["One", "Two", "Three", "Four"]
    var combinedString : String = ""
    for string in stringArray{
        combinedString.append(string)
    }
    print(combinedString)
    // combinedString = "OneTwoThreeFour"

    Alternatively, it can be done using reduce function on the array.

    var stringArray = ["One", "Two", "Three", "Four"]
    let combinedString = stringArray.reduce("", {$0 + $1})
    print(combinedString)
    // combinedString = "OneTwoThreeFour"
  4. FlatMap: When it’s implemented on the sequences, it flattens a collection of collections. It’s best case scenario is, removing nil from the collection.

    Let’s say you want to combine the nested array in below array. It’s done as below using for loop.

    let numberArray = [[1,2,3,4,5],[7,8,9,10]]
    var combinedArray: [Int] = [Int]()
    for number in numberArray{
        combinedArray = combinedArray + number
    }
    print(combinedArray)
    // combinedArray - [1, 2, 3, 4, 5, 7, 8, 9, 10]

    Alternatively, it can be done using flatMap in single line of code.

    let numberArray = [[1,2,3,4,5],[7,8,9,10]]
    let combinedArray = numberArray.flatMap { $0 }
    print(combinedArray)
    // combinedArray - [1, 2, 3, 4, 5, 7, 8, 9, 10]

Here are some advantages of using Higher Order Functions.

  • It helps to read and understand complex programming
  • Helps to write simple and short code and better readability
  • Improve the Swift language coding

Optionals (?) in Swift


Optionals is one of the great thing in Swift but also working with it can be bit clumsy sometimes. Unwrapping and checking if there is value can be time consuming and get tempted to add exclamation (!) mark to force unwrap the value. It’s dangerous as force unwrapping leads to crash of app if optional doesn’t have a value.question-mark-1019993_960_720

Here is brief about what’s optionals and different types of optionals usage.

What’s Optionals: Optionals are value type in swift with “there is some value and value is ‘X’” or “there isn’t any value at all”. It’s powerful Enum with values None or Some(T). It creates the safe variables and avoid the runtime crash by initializing variables with nil.

var str: String?
 print(str) // prints null
 var str: String
 print(str) // compile time error as variable is used before initialization

Here are different ways to handle the optionals in the code base.

  • Forced unwrapping: If variable has been defined as optional, it’s required to unwrap it before it’s been used

     var str: String?
     str = “Hello World!”
     print(str) // It will print - Optional(“Hello World!”)
     print(str!) // It will print - “Hello World!”
  • Automatic unwrapping: Alternatively, variable can be defined with automatic unwrapping option. It would be “!” instead of “?”

     var str: String!
     str = “Hello World!”
     print(str) // It will print - “Hello World!”
  • Optional Binding: It’s the way to check if optional type variable has value and if it has value, it would be assigned to temporary variable / constant

     var str: String?
     str = “Hello World!”
     if let str = str{
      print(str) // It will print - “Hello World!”
     }
  • Nil-Coalescing Operator: The Nil-Coalescing Operator (a ?? b) unwraps an optional if there is value or returns a default value. The expression b must match the value type stored in a.

     var str: String?
     let newStr = str ?? “Hello there..” 
     print(newStr) // It will print - “Hello there..”
  • Optional Chaining: It’s process of calling/querying methods,  properties, subscripts on an optional which might have nil value. If optional have value, the property, methods, subscripts will return value otherwise it would return nil.

    func albumReleased(year: Int) -> String? {
    switch year {
        case 2006: return "Taylor Swift"
         case 2008: return "Fearless"
         case 2010: return "Speak Now"
         case 2014: return "1989"
         default: return nil
         }
     }
     print(albumReleased(year: 2006)?.uppercased()) // It will print - TAYLOR SWIFT

How Deploy App to iOS Device with archive file


While developing app for iPhone sometime there are scenario’s where you need to test the app on actual device. Straight forward way, you just plug-in the phone and run the app by pointing to the test device and it’s ready to test.

But there are scenario’s like your iPhone is using latest version of the iOS and XCode is having previous version so you wouldn’t be able to get the app directly. There is hacky way to deploy the app to such devices. Here are the steps.

  1. Create “Archive” for the app
  2. On Archived app, click “Show in finder” and locate “.xcarchive” file you created in step # 1
  3. Click on the .xcarchive file and select “Show Package Contents”
  4. In the opened folder, select “Products –> Application” and you will have your application
  5. Drag the app to your iTunes Apps so it can be installed on the test device
  6. Connect the test device and install the app by applying the changes

Hope this helps, let me know if any questions.

How to create UITableView with dynamic cell height


It’s quite simple, just add estimatedHeightForRowAt function in UITableViewController with default height for the cell.

    override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {

        return 44.0

    }

Few things to remember are:

  • It can be used for dynamic table view only. For Static table view it will not work
  • If you have custom cell, add all required constraints to make sure layout is intact. simulator-screen-shot-jan-12-2017-12-18-27-am

Promise – #MakePromise & #KeepPromise


It’s simple way to create, share, track and achieve goals. You create a promise (Goal) and share it with friends, family so they will be rooting for your success. They would be able to send messages to you for motivation and we will send you daily motivation message customized for your promise.

Promises can be anything, as simple as walking around a block everyday to running a marathon this year or new year resolutions. Study shows promises are kept compared to wish list of resolution. You make a promise and we will help you to keep it. Also there is higher chance of keeping your promise if it’s shared with well wishers.

Promise, is upcoming app for simple way to make the promise and keep the promise. Signup Today to get notified once this free app is available for download.

Any suggestions, feedback to make this app more useful for you?

This slideshow requires JavaScript.

 

Moving and movers, stay away if possible 


Moving is always painful and if it’s long distance it becomes nightmare.

We moved from Jacksonville, Florida to Jersey City, NJ and used Trans Van Line movers for moving my things, Here is little bit story! They doesn’t seems to be real movers, they are sort of agent and very bad at it. My move was planned for Oct 1st week and it had moved to 2nd week due to hurricane in that area. Understandable, it’s beyond anyone’s control. They told movers will come to pickup things on Monday and that keep shifting by 2 days whenever I call them. They told they will give me 24 hours advance notice before coming and they called me at 11 AM on Friday saying they are coming at 1 PM. As I was already fed up with waiting, I said ok. They came at 5 PM instead of 1 PM and when they came, mover guy told, you have more things than what you told us. Only extra thing I had was one folding table and small rack. I said, don’t worry about those and pack everything else. They packed such a way it takes lot of space and after packing everything and loading into truck they said it’s more than what you reserved. I didn’t reserve any space, I just asked movers for moving my things from the list. It’s their problem how they are packing it. After loading everything they changed my quote from $1,200 to $2,300 without any previous notice. It’s for the same items I had listed in the quote plus couple of other small items. I can understand couple of hundreds but double of original quote? Mover called to his manager and his manager was threatening to leave all the items there and don’t want your business unless you pay $2,300. When I said, I don’t want your service, they were asking for $500 to unload the items. All this started after loading the items into the truck. Worst experience for moving. Not at all good for follow-up or any questions, be it over the email or call. To get speaking to someone it takes few calls and don’t expect any call back for voicemails. They charged additional $275 for bringing my items to my home as it was one way street and their large truck couldn’t enter, I understand and was ok with it. After unloading all the items, my king size bed is completely damaged and I’m running from pole to post to get claim for it. When I call, they transfer to someone who don’t pickup or just hang up the call. Finally when it was transferred the person who spoke said, full value is not insured and you would get 60 cents ($0.60) per pound! Seriously, while booking they said everything is covered if it’s packed by movers. I don’t know if I’ll get any claim done if it’s done.  Oh, I got my items after 3 weeks of pickup and I had been told it would be 7 – 10 days when they picked up.

If you need to use movers, take below things into consideration. 

  • Planning: Check with multiple moves and see what works for you. Just don’t go for whoever quotes the lowest, check what kind of service they provide, whether they cover the insurance, what’s charges for extra luggage, etc. Also List down all the things you are planning to move including each and every small piece. e.g. white board or what kind of bed you have. Send pictures of your items or have movers come over to see so they can quote accurately.
  • Read contract line to line, word to word: Most of us are very bad at reading long contract of multiple pages, it’s very important to read the movers contract. Most of the time what they are saying over the call is different than what’s in the contract. Once you sign the contract, if you have any questions, there answer is refer to the fine printed contract.
  • Have low expectations : Don’t expect the move to be perfect, some things may break and you may not have good service from movers. It’s irrespective of what they promise.
  • Cleanup your belongings and move: To reduce extra items and few low hanging items, better sell them before planning the move. It may be better you sell something which cost $50 and require you to pay $100 for move. You can always buy it at new location. for example, office table. 
  • Be prepared for delays: Most of the movers says they will deliver it in 3-4 days or a week but expect delays as most of them have 30 business days to deliver in contract. Expect delays and plan accordingly.