Wednesday, October 03, 2018

Python script: MapIt.py


Based on an example, script of mapIt.py, from the video of Automate the Boring Stuff with Python, I figured out that the codes should be changed in Mac OS X, as I mentioned that there are multiple versions of python in Max OS in my previous blog.

In addition to those changes, there are some steps that should done in Mac to make the script as executable in terminal. I further make it working in Spotlight as well. Here are my notes.

Script

Based on the video, I made minor changes on the script. Here is what I have now:


  1. #! /usr/bin/env python3
  2. import webbrowser, sys, pyperclip
  3. sys.argv  # example ['mapit.py', '870', 'Valencia', 'St.']
  4. address = 'Home'
  5. if len(sys.argv) > 1 :
  6.    address = ' '.join(sys.argv[1:]) # ['870', 'Valencia', 'St.']
  7. else :
  8.    address = pyperclip.paste()
  9. # https://www.google.com/maps/place/<address>
  10. webbrowser.open('https://www.google.com/maps/place/' + address)

The first line is important if you want to run the script directly from terminal or Spotlight. Still there are some other steps to be done in order to run the script directly from terminal or Spotlight.

Notice that I specify the name of python is python3! Another minor change is the default address value: Home. I am using Mac and the Google map knows where my home is in my local Mac account.

I saved the script at my local user account path: ~/Programming/py/mapit.py With script ready, I test the script in terminal:

...$ python3 Programming/py/mapit.py Park Ave 83 St New York

As soon as I type in the above command, a new tab page of Google Map is opened in Safari with the correct address.



Make the Script Executable

So far so good. However, I would prefer to open the script directly from terminal, or from Spotlight, without specifying python3. For the case of terminal, first I have to make the script executable with the following commands:

...$chmod a+x ~/Programming/py/mapit.py

The second step is to add my script path to env PATH so that I can simply type in mapit.py anywhere in command line. This is done by adding the path in ~/.bash_profile:

  1. PATH="/Library/Frameworks/Python.framework/Versions/3.7/bin:${PATH}:/Users/dchu/Programming/py"
  2. export PATH

With above setup ready, now I can run the script anywhere in terminal:

...$ mapit.py Donggaodi Hongxing St Beijing

Isn't that cool?




Make the Script Runnable in Spotlight


Spotlight on Mac is a very convenient way to launch an app, to open a file, and to find information. However, unlike Windows Run, it not the way to direcly launch an app with arguments. Even though I set my script mapit.py as executable, I cannot run it from Spotlight. It will only open the script in Xcode!

One way to get it work in Spotlight is to change the script to .command extension. Mac OS will recognize this type of file as a runnable command.

I prefer to keep my script as .py. In UNIX or Mac, I can create an alias file of script: hard link(only hard link works in Spotlight). Here is the command to set it up:

  1. ...$ cd ~/Programming/py
  2. ...$ ln mapit.py mapit.command

The good thing is that any change to my script will be automatically reflected in the command file.

In order to open the Google Map with specified address, I need to copy the address to clipboard first. Then I open my Spotlight and type in mapit.command. It will pick up the address and open Google map in my default browser.

The only thing is that I cannot specify address directly as arguments in Spotlight. This is the limitation of it, and I cannot find a way to do that.

This is why I need to use pyperclip package in my script.




Note: another minor thing has to be done to make it runnable cleanly. The command is running in terminal. When the Spotlight launches the command and opens the map in browser, it will leave the terminal in open status. I prefer to close the terminal automatically.

To do that, go to terminal Preferences..., change the shell setting to Close the Windows:




The last word I have to say is that even the python script is very powerful and convenient to open a map with an address. I think Mac's Automator is much more powerful. It is easy to create (as a service), and can be set to selected text to open a map. Even though, I think it is a very good practice and great programming experience.

References


Read More...

Tuesday, September 25, 2018

Python and Packages

Recently I started to watch a long training video on YouTube, 9+ hours. I just spent fraction of a few minutes daily as alternative refreshment. During the training period, I tired to use Idle app to practice some codes. Up to the point of installing third party packages, I could not get import to work on my Mac. I spent couple of days struggling and finally I figured it out. I think it is worthwhile to take some notes about this experience.

Tool to Install Packages


The first hurdle is that there is no pip, a tool to install third party python packages, available in terminal on Mac. It seems that python is part of Mac OS system, but the version of python is an old version: 2.5 & 2.7. pip was not installed on my Mac.

Eventually I got pip installed by using easy_install tool:

sudo easy_install install pip

After that, I could install pyperclip, a package for using clipboard copy and paste features.

sudo pip install pyperclip

However, the import of pyperclip in python shell and script still does not working!

Version Issue

I could not find out any solution from web easily. It seems that all the solutions in the top search list I found from web are old ones, ie for python 2.*. From one place I read a hint about the issue: different versions of python on Mac. It is true that python came with Mac OS is version 2.3, 2.5 & 2.7. The newest version, for the time being, I installed on Mac is python 3.7.

Further investigation, I found that the tool of pip is actually used to install packages for python 2.7. The pip is located at the path of:

/Library//Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/pip

The tool I need to install pyperclip is actually pip3! This one is at the path of:

/Library//Frameworks/Python.framework/Versions/3.7/bin/pip3

When I sorted it out, it is so easy to install third party packages for python 3.7. For example:

sudo pip3 install pyperclip

For my interest, I further found out the locations of packages for different versions. For python 2.7, the location of package is at:

  1. find /Library/Python/ -name pyperclip
  2. /Library/Python//2.7/site-packages/pyperclip

and for python version 3.7 it is at:

  1. find /Library/Frameworks/Python.framework/ -name pyperclip
  2. /Library/Frameworks/Python.framework//Versions/3.7/lib/python3.7/site-packages/pyperclip


Python also in Different Versions!


One more interesting thing I found out is that, on my Mac, the name of python executable also has different ones! For the python came with Mac OS is actually version 2.5, and the executable name is python:

/Library//Frameworks/Python.framework/Versions/2.5/bin/python

and for the newest version, 3.7 I installed, the name is python3:

/Library/Frameworks/Python.framework//Versions/3.7/bin/python3


From the terminal, the command of python will bring up to version 2.5:

  1. ...$ python
  2. Python 2.5 (r25:51918, Sep 19 2006, 08:49:13)
  3. [GCC 4.0.1 (Apple Computer, Inc. build 5341)] on darwin
  4. Type "help", "copyright", "credits" or "license" for more information
  5. >>>

or type option -h to get all available options. -V is for getting python version:

  1. python -h
  2. ...
  3. Python 2.5


In order to run python3 from terminal, the PATH has to be changed: adding python3's path. This is the result of my updated PATH:

  1. echo $PATH
  2. /Library/Frameworks/Python.framework/Versions/3.7/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:

The PATH is set in the file of .bash_profile:

    more ~/.bash_profile

  1. # Setting PATH for Python 3.7
  2. # The original version is saved in .bash_profile.pysave
  3. PATH="/Library/Frameworks/Python.framework/Versions/3.7/bin:${PATH}:/Users/dchu/Programming/py"
  4. export PATH

Even with this change, you have to type the correct python executable name, ie python3, to enter python shell:

  1. python3
  2. Python 3.7.0 (v3.7.0:1bf9cc5093, Jun 26 2018, 23:26:24)
  3. [Clang 6.0 (clang-600.0.57)] on darwin
  4. Type "help", "copyright", "credits" or "license" for more information.
  5. >>> import pyperclip
  6. >>>

Finally, I could do import pyperclip in python shell and scripts without any errors.

By the way, here are the options to get all the commands, options, and the version for the tool of pip or pip3:

  1. pip -h
  2. ...
  3. pip -V
  4. pip 18.0 from /Library/Python/2.7/site-packages/pip-18.0-py2.7.egg/pip (python 2.7)
  5. pip3 -V
  6. pip 10.0.1 from /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/pip (python 3.7)


References



Read More...

Monday, September 17, 2018

Access to iOS Device Sandbox Data

If you have some files, database for example, in your iOS app, you may need to access to them. Recently, while I was working my app update, I was not sure if a major change would cause to lose my database. Before I run the app on my iPhone, I would like to keep a copy of my database to avoid any risk to lose my data over years.

There are couple ways to do that.

Backup to iTunes


This is very common way to keep a backup of a whole iOS device. First lunch iTunes on a Mac/Windows. Then connect your iPhone to the Mac/Windows. Click on iPhone icon to open a view, where backup is available.

This is very convenient to keep a backup before any adventure or after a period of time. In case of screwup, you can easily to restore your iPhone back to your previous status.

However, with this method, you could not see any files in your app sandbox, nor you could make any changes.

Devices in Xcode


The second way to make a backup of an app is available in Xcode. First, set your iPhone as target or active scheme. From the menu of Windows->Devices and Simulators, open a view.



Here is the view:



Select the app you want to make a backup, then click the gear icon to bring up a menu list. In this way, the whole app sandbox is backed up to your local Mac. The content of the backup can be viewed through Show Package Contents context menu.



This is pretty cool! Not only I can easily to restore the sandbox back to my iPhone, I could also view the content what I have in the app on my iPhone device. For example, the core data database, as you can see, is actually based on several files, all beginning with the same prefix name, defaultDatabase, as I choose it as database name for my app.

When I run my app in Xcode simulator, not only I could view, but also I could access to my app sandbox from Finder. There is no need to download or upload files to my app sandbox in Simulator.

I think that I could make some changes in the backup and restore back with changes I need. This is really handy for iOS developers in case needed.

Notice that you can only access to the app you are in development and installed to the device from Xcode, and the app has to be on your device. You can not see any other apps. If your app is installed through App Store, or Test Flight, you could not see it. This is for security reason. Anyway, it is good enough for me.

The Xcode I use is version 9.4 and iOS is version 11.4.

References



Read More...

Thursday, August 23, 2018

ActionSheet as PopOver View

Recently, I have been working on my app update. In some cases, some actions could not be performed. I need to present a view to explain the reason. Alert view is a very common method to do that. Alert view is good to present the information, however, it is a modal view. User have to tap on OK or Cancel button to dismiss the alert view. I prefer the method of a popover view as alternative.

It is very easy to do that by using the same UIActionControler, and set the style as .actionSheet. This is well explained in Nick Meehan's post. Still there some thing missing is his post.

I would like to support both iPhon and iPad. For iPhone case, an action button should be added to dismiss the view. By default, the view is still a model view. You need a way to dismiss the alert view.

It is very interesting to find out that an action with .cancel style will change the modal view into a popover view. Further investigation, there is no need to add action handler to dismiss the view. The actionSheet will behaviour like a popover in iPhone.

Here are some codes.

  1. if let popoverController = alertController.popoverPresentationController {
  2.  popoverController.sourceView = view
  3.  popoverController.sourceRect =
  4.    CGRect(x: view.bounds.midX, y: view.bounds.midY, width: 0, height: 0)
  5.  popoverController.permittedArrowDirections = []
  6. } else {
  7.  let cancelAction = UIAlertAction(title: UIHelper.dismissButtonTitle(), style: .cancel)
  8.  alertController.addAction(cancelAction)
  9. }


Another interesting thing is that the cancel style action button will be displayed as an separate button on the bottom. You can specify any title to the button. I like it. This is the UI as in some Apple apps, such as deleting a message in message app.

Here is what I achieved in my update:



References


Read More...

Thursday, June 21, 2018

Debugging with Xcode and LLDB

Really cool stuff on lldb, Xcode debug power tool. As well there is one training video from WWDC 2018: Advanced Debugging with Xcode and lldb.



Read More...

Tuesday, April 17, 2018

Pace Calculation in Swift

I need to add a new feature to show pace in my iOS App(TapToCount -3W). By given two dates and two locations as input, the pace can be easily calculated in the formula:

pace = duration / distance

Duration

In swift the duration can be obtained in following codes:


// dt1 and dt2 are Date types
let timeInterval = dt2.timeIntervalSince(dt1)

The func timeIntervalSince call will return seconds as time interval between two days.

Distance

The distance between two locations is obtained

// loc1 and loc2 are CLLocation type
let dist = dist2.distance(from: dist1)

where dist is the distance value in meters.

Support Localization and Accessibility

It seems that the pace calculation is so simple to get. Hold on. iOS provides APIs to support metric or imperial measurement system. It would be nice to get pace calculation result either in metric or imperial system. This can be easily detected by the following codes.


let locale = NSLocale.current
let metricSystem = locale.usesMetricSystem

In my iOS app, I presented the pace calculation result in human readable format. For example, 6'34" would be "6 min, 28 secs".

Further more, the pace result may be in hours, or even years, depending on inputs of dates and locations. My pace calculation is more generic to support a wide range of cases. To obtain readable result, it can be done by using Swift codes:


1 let fm = DateComponentsFormatter()
2 fm.allowedUnits = [.year, .day, .hour, .minute, .second]
3 fm.unitsStyle = .short
4 let short = fm.string(from: value)
5 fm.unitsStyle = .full
6 let full = fm.string(from: value)

The allowedUnits property specifies what readable units should be used. Here is the complete units from seconds to years, and only first none zero value's unit will be presented, for example, 2 hrs, 15 min, 23 secs. This example is in a short form. There is no need to worry about languages. The API will do the localization automatically. Very nice!

The short form is good for UI presentation. The full form will spell out whole units, such as "2 hours, 15 minutes, 23 seconds". This would be great for accessibility support, for example, label's accessibilityValue. The localization for full form is done automatically as well.

I tested this pace calculation in my iOS app. The following is the screenshot of my mountain hiking, Ha Ling Peak, last Sunday.



and this is my running result today when I was doing my test.




and here is one more test I did. I changed the iPhone language to Traditional Chinese.



You may notice that when the pace result is in years or long days, the last units minute and second are dropped out, since such small amount is so insignificant.  The complete codes are available in my answer in StackOverflow discussion.

References




Read More...

Sunday, January 14, 2018

Autoresizing and Constraints to Safe Area

Recently one issue has troubled me for several days. Finally I just figured it out. I think it is worthwhile to make a note about my experience.

I have an app with several tab views, all displaying similar data in table view. I tried to add search feature for the app. The way to add search controller for iOS 11 and iOS 10 is different. For iOS 11, the search controller is added to navigation controller while the search controller is added to table view's header for iOS 10. My test of iOS 11 works great. However, the test for iOS 10 presented an issue.

In the first tab view, the search works well, but not in the second one. The issue is that the content of table view is shifted up about 40 pixels in the second tab.

Here is the search bar at initial status:



Tap on search bar to start search. Notice that the content of table view is shifted up 40, about half of the first row is behind the search bar.



Even worse, I could not see the search bar if I select a row to the next screen and back to the main screen. The search bar is moved up, not in reachable view.



The search function in the first tab view works without this issue. Therefore, the best way is to compare the difference between two tab view controllers. There are not any major difference. I tried to disable some codes in viewDidLoad, viewWillAppear, and viewDidAppear to make them behaviour the same. Still I could not resolve the issue.

Finally, I noticed there is a difference in storyboard. The table view of the first tab is using autoresizing.



while the second tab's view controller uses constraints for its table view!



I removed four constraints and set autoresizing for the table view of the second tab. With this change, the search feature works well as expected.

It seems that autoresizing for iOS 11 is almost as same as four constraints to its safe area (which is introduced in iOS 11 but not exist in iOS 10). Even it would fall back to previous layout guide, it seems not working in the same way for table view in this case. For old iOS back from 11, try to not use safe area as reference for table view constraints.

Test for all supported iOS versions is very important!

Read More...

Monday, December 04, 2017

iOS 11 New Feature: Displaying Large Size Content

iOS 11 introduce many great features. One of them is display large size content, for example, text and images. With small size of mobile devices, for many people it is really hard to read small text or content. With this new feature in iOS 11, I want to support it in my app.

One new change is the large size title in navigation control. Another one is dynamic size for text views. PDF format for images is also great to avoid making various size of images in project.

There are two very good videos to watch as in the reference.

References


Read More...

Monday, November 13, 2017

Dynamic Height of TableView Cell

For table view in iOS, its cell could be one of several styles: basic, detail, subtitle and custom. The first 3 are built-in style. The title, subtitle, and detail are labels in the cell. By default, those labels cannot grow vertically if text in the label is too long. I found out there is a property for label to control if displaying only one or multiple lines: numberOfLines. By default, this property is one.

If you change the property to 0, the label may grow vertically to show all the text in it. That means the view cell in a table view could grow dynamically in height. This is true for the first three styles. However, for the custom view cell, it is tricky.

Recently, I was working on my iOS app to enhance its user interface. One of table views contains custom view cell. I would like to show cells in dynamic height if labels in the cell having long text. At first, I tried to set up enough constrains in the custom view cell so that no any warning nor errors in storyboard. However, my view could not show dynamic cell height.



It seems that all cell height are the same.

Finally I figured out why. The contrails in the custom view cell have to be enough for UIKit to calculate the height. In my view, I placed three labels one by one vertically. From top to bottom, I set constrains one to next vertically. However, I did not add a constrain from the last label to the bottom. As a result, UIKit could get the height of view cell.



I added the constrain to make sure the last label's bottom related to the bottom of its container. With this change, I got my app working as expected.




Enough-constrains-for-vertial-span is a trick for custom table view cell. There are other things which have to be set for dynamic cell height. See the reference blog for detail.

By the way, my app supports several languages. Therefore, for this update, I have to make all the changes in all language views in storyboard. You may notice that the messy one above is in Chinese, and the next expected one is in English. By the time I am writing this blog, I have not updated my Chinese view yet.

Reference


Read More...

Wednesday, November 08, 2017

Grey blank toolbar on TableView

During my work on my iOS app (TapToCount - 3W), I had a very bizarre issue. There is grey blank toolbar appearing above tab bar on one of tableview controller.

Problem


Actually, the main view with tableview looks OK initially. A grey blank tool bar appears above tab bar after back from a detail view.



The detail view is popped up from the main view when a row of tableview is selected by using navigation controller. The detail view shows a toolbar with some buttons, but no tab bar. Look at detail view, I notice that the tool bar actually is raised up from bottom.




I tried to find what settings triggered this problem from storyboard on both main and detail views, as well as my codes for those views. I could not find anything wrong.

One thing I noticed is that the English version runs good. The problem only appeared on my Chinese version (when I changed iOS language to simplified Chinese, but traditional Chinese is good). I think that it must be something I might changed in storyboard for simplified Chinese. Most unlikely in my view controller codes.

Snapshots to Find out Differences


I am using MaBook Air 2014 on my App. There are tens of property settings in a view. It is really very painful slow (about 40 secs) to compare those settings switch back and forth between Chinese and English storyboards. I found a trick to do the checking, taking snapshots of property settings in one language and then using those snapshots to compare property settings in another language.

Interesting thing is that both main and detail views are exactly same! That puzzled me. Soon I realize that the view is driven by navigation controller. There might be something different in navigation controller. There are several navigation controllers: root view controller (tab view controller as start), master view controller (split view controller), and navigation controller.

From those view controllers, I found the differences!







I am not sure what those marked settings mean. I changed the settings in views of Chinese storyboard. voilà! It works!

Here is the current version of views for the same problem ones as in above.






Conclusion


Sometimes, it may be hard to find out straight solutions either from my own knowledge/skills or internet. There may be some other ways to target the issue. Here is an example, from working version as start, then trace down the difference in the problem target.

I am not going to explain what caused the problem. I may figure out reason behind those property settings. This blog is just a note about my programming experience and growth.

Read More...

Monday, October 02, 2017

Container View Pushed Down in Navigation View

After I transferred my codes from Swift 3.0 to 4.0 in Xcode 9.0, I noticed that one of view's content is pushed down about the height of navigation bar. Before my app was working fine.

After hours investigation I still had no clue. Then I searched from Internet. Soon I found one solution. It is not obviously related my conversion. It is just the navigation bar in the previous navigation controller has to be set Translucent! With that change my views in all localization back to normal. Love StackOverflow and solution offered by developers!

Reference






Read More...

Monday, September 18, 2017

My First iOS App is Released!

Today is important date, Sept 18, 2017 Monday, for me. My first iOS app: TapToCount - 3W is released on the App Store!

I submitted my app last Friday and I got several email notifications about the app status. After I completed all the required information submission, the app is released on the App Store. That's approval process is a surprise for me.

The app is universal one, i.e., for iPhone and iPad. However, I have not got screenshots for iPad yet, so the current app is only for iPhone. I hope I'll get it ready for iPad soon.

Currently the first version is available at US, Canada, British and Australia, English speaking countries. The app does support Chinese, bot Simplified and Traditional ones. I am in the process of preparing screen shots for Chinese stores.

References


Read More...

Friday, September 15, 2017

Change Blogger's Theme

Recently I created a new blog for my iOS app: TapToCount - 3W.

For this web blog, I choose a theme from blog settings. The layout looks fine, except the main page displays an image from my first blog as background image at the top. It stretches ugly taking a lot of spaces on the top.

I need to disable this from the theme. After exploration on the theme's html codes, I found a simple way to disable it.



As marked in red box, I changed the variable "hasImage" to "hasImages". This minor change of variable name makes the block of html codes not embedded into the main page.

This is a note about what I did. Otherwise, I may forget what I did in the blog's theme.

References


My new blog: TapToCount - 3W

Read More...

Thursday, August 17, 2017

WWDC 2017 Vedios

WWDC 2017 is over (Jun 5-9, 2017). As I did in the past years, I finally finished watching all videos of WWDC 2017 provided by Apple. There are 136 videos (49+19+15+5+4+10+15+19), each ranging from 10 minutes to over 2 hours, most around 30+ minutes. So I guess the total length of the video is about 70 hours.

Here is the list of videos I watched:

WWDC 2017

Platforms State of the Union - 102
Introducing Core ML - 703
Introducing ARKit: Augmented Reality for iOS - 602
Introducing Metal 2 - 601
Introducing Drag and Drop - 203
What's New in Swift - 402

App Frameworks

  1. Advanced Animations with UIKit - 230
  2. Advanced Touch Bar - session 222
  3. Advances in TVMLKit - 202
  4. Build Better Apps with CloudKit Dashboard - 226
  5. Building Apps with Dynamic Type - 245
  6. Building Great Document-based Apps in iOS 11 - 229
  7. Building Visually Rich User Experiences - 235
  8. Choosing the Right Cocoa Container View - 218
  9. Cocoa Development Tips - 236
  10. Connecting CareKit to the Cloud - 239
  11. Customized Loading in WKWebView - 220
  12. Data Delivery with Drag and Drop - 227
  13. Deep Linking on tvOS - 246
  14. Drag and Drop with Collection and Table View - 223
  15. Efficient Interactions with Frameworks - 244
  16. Extend Your App's Presence With Sharing - 247
  17. Extend Your App’s Presence with Deep Linking - 250
  18. File Provider Enhancements - 243
  19. Filtering Unwanted Messages with Identity Lookup - 249
  20. Focus Interaction in tvOS 11 - 224
  21. Introducing Business Chat - 240
  22. Introducing PDFKit on iOS - 241
  23. Introducing Password AutoFill for Apps - 206
  24. Localization Best Practices on tvOS - 248
  25. Making Great SiriKit Experiences - 228
  26. Mastering Drag and Drop - 213
  27. Media and Gaming Accessibility - 217
  28. Modern User Interaction on iOS - 219
  29. Natural Language Processing and your Apps - 208
  30. Now Playing and Remote Commands on tvOS - 251
  31. The Keys to a Better Text Input Experience - 242
  32. The Life of a watchOS App - 216
  33. Touch Bar Fundamentals - 211
  34. Updating Your App for iOS 11 - 204
  35. What's New in Accessibility - 215
  36. What's New in CareKit and ResearchKit - 232
  37. What's New in Cocoa - 207
  38. What's New in Cocoa Touch - 201
  39. What's New in Core Data 210
  40. What's New in Core Spotlight for iOS and macOS - 231
  41. What's New in Foundation - 212
  42. What's New in Health - 221
  43. What's New in MapKit - 237
  44. What's New in Safari View Controller - 225
  45. What's New in SiriKit - 214
  46. What's New in iMessage Apps - 234
  47. What's New in tvOS - 209
  48. What's New in watchOS 205
  49. Writing Energy Efficient Apps - 238
Design
  1. 60 Second Prototyping - 818
  2. App Icon Design - 822
  3. Communication Between Designers and Engineers - 809
  4. Design Tips for Great Games - 811
  5. Designing Across Platforms - 804
  6. Designing Glyphs - 823
  7. Designing Sound - 803
  8. Designing for Subscription Success - 814
  9. Designing for a Global Audience - 819
  10. Essential Design Principles - 802
  11. Express Yourself! - 820
  12. Get Started with Display P3 - 821
  13. How to Pick a Custom Font - 815
  14. Love at First Launch - 816
  15. Planning a Great Apple Watch Experience - 808
  16. Rich Notifications - 817
  17. Size Classes and Core Components - 812
  18. What’s New in iOS 11 - 810
  19. Writing Great Alerts - 813
Developer Tools
  1. App Startup Time: Past, Present, and Future - 413
  2. Auto Layout Techniques in Interface Builder - 412 very nice on storyboard layout!
  3. Debugging with Xcode 9 - 404
  4. Engineering for Testability - 414
  5. Finding Bugs Using Xcode Runtime Tools - 406
  6. GitHub and the New Source Control Workflows in Xcode 9 - 405
  7. Localizing Content for Swift Playgrounds - 410
  8. Localizing with Xcode 9 - 401
  9. Teaching with Swift Playgrounds - 416
  10. Understanding Undefined Behavior - 407
  11. What's New in LLVM - 411
  12. What's New in Signing for Xcode and Xcode Server - 403
  13. What's New in Swift - 402
  14. What's New in Testing - 409
  15. What’s New in Swift Playgrounds - 408
Distribution
  1. Advanced StoreKit - 305
  2. Introducing the New App Store - 301
  3. What's New in Device Configuration, Deployment, and Management - 304
  4. What's New in StoreKit - 303
  5. What's New in iTunes Connect - 302
Featured
  1. Convenience for You is Independence for Me - 110
  2. From Monroe to NASA - 106 - NA yet
  3. Platforms State of the Union - 102
  4. WWDC 2017 Keynote - 101
Graphics and Games
  1. From Art to Engine with Model I/O -610
  2. Going Beyond 2D with SpriteKit - 609
  3. Introducing ARKit: Augmented Reality for iOS - 602
  4. Introducing Metal 2 - 601
  5. Metal 2 Optimization and Debugging - 607
  6. SceneKit in Swift Playgrounds - 605
  7. SceneKit: What's New - 604
  8. Using Metal 2 for Compute - 608
  9. VR with Metal 2 - 603
  10. What's New with Screen Recording and Live Broadcast - 606
Media
  1. Advances in Core Image: Filters, Metal, Vision, and More -510
  2. Advances in HTTP Live Streaming - 504
  3. Apple Podcasts - 512
  4. Capturing Depth in iPhone Photography - 507
  5. Error Handling Best Practices for HTTP Live Streaming - 514
  6. HLS Authoring Update - 515
  7. High Efficiency Image File Format - 513
  8. Image Editing with Depth - 508
  9. Introducing AirPlay 2 - 509
  10. Introducing HEIF and HEVC - 503
  11. Introducing MusicKit - 502
  12. Vision Framework: Building on Core ML - 506
  13. What's New in Audio - 501
  14. What's New in Photos APIs - 505
  15. Working with HEIF and HEVC - 511
System Framework
  1. Accelerate and Sparse Solvers - 711
  2. Advances in Networking, Part 1 - 707
  3. Advances in Networking, Part 2 - 709
  4. Best Practices and What’s New in User Notifications - 708
  5. Core ML in depth - 710
  6. Creating Immersive Apps with Core Motion - 704
  7. Developing Wireless CarPlay Systems - 717
  8. Enabling Your App for CarPlay - 719
  9. Introducing Core ML - 703
  10. Introducing Core NFC - 718
  11. Modernizing Grand Central Dispatch Usage -706
  12. Privacy and Your Apps - 702
  13. What's New in Apple Pay & Wallet - 714
  14. What's New in Core Bluetooth - 712
  15. What's New in HomeKit - 705
  16. What's New in Location Technologies - 713
  17. What's new in Apple File System - 715
  18. Your Apps and Evolving Network Security Standards - 701
  19. iOS Configuration and APIs for Kiosk and Assessment Apps - 716

References


Read More...

Friday, August 04, 2017

Self-reference and clousure

Here is a great short video explaining reference type and how to properly use it in closure by Brain's How to Build That App in YouTube.



Read More...

Wednesday, June 28, 2017

TestFlight for iOS Developers and Testers

TestFlight is an app provided by Apple. Here is the description by Apple about it:

TestFlight makes it easy to invite users to test your apps and collect valuable feedback before you release them on the App Store. You can invite up to 2,000 testers using just their email address.




Recently I have been using TestFlight app to deliver my app to testers. I found that this is a great platform between iOS app developers and app testers.

Add Testers by email

To make an app available for iOS users/testers to install and to test the app on their iOS devices, what an app developer needs to do is to request email from testers.

Then the developer adds the email to developer's test list from Apple iTunes Connect account. Tester will receive an email about test request.

From my experience, testers should first install TestFlight app from App Store on their iOS devices. This will make it easier to click or tap on the request email and see the app in TestFlight right away. Otherwise, testers will have to enter redeem code from the request test email.



Using TestFlight

Even though testers could open app directly on their iOS devices after initial installation, I would recommend to launch or open app each time from TestFlight. One of advantages is that testers will get the latest version from there. From TestFlight testers would notice new upgrades if the version of app is old.




From TestFlight, testers are able to see and install all previous versions, as well as description provided by developers. Tap on an app will provide more information about the app, information, Previous Builds, and more. This provides a convenient way to compare, verify and test issues found in the app.




If app is installed through TestFlight on one iOS device, the tester can also install the same app on other iOS devices (iPhone or iPad) by using the same AppleID, and then continue to his/her test on various iOS devices.

Send Feedback to Developers

TestFlight provides “Send Feedbacks” as a way to communicate with developer. The feedback is sent out by email. Therefore you can attach additional information such as screenshots, notes, and any related information. To add attachment in email, tap and hold on email body. Then a popup menu will show options to add photos.




I would strongly recommend testers sending at least one feedback to developer, even none issues are found. This will let developer know at least what iOS devices testers are using.

Welcome More Testers

Anyone with iOS devices 9.3 or higher are welcome to test my app, TapToCount - When, Where & What. What you need to do is to pass me your email. I will add you in my tester list.

As mentioned before, please install TestFlight app from App Store first. Then open TestFlight with your Apple ID.

One thing I notice is that you need to have Wifi or Cellular connection when you use TestFlight. It will connect to Apple server to find out what apps are available for your TestFlight. This will cost very small data communication. To install or update app, Wifi connection is recommended if data is concern for you.

You will receive test request by email for the first time. Tap on the link in email on your iOS device. You will see my app in TestFlight ready for installation. As my recommendation, open my app from TestFlight easy time. This will guarantee you will test my App in the newest version.

Keep in mind, there is 90 days expiration to use/test app through TestFlight. During your test period, please send me at least one of you test results, comments and any bugs or crashes you found.

References


Read More...

Wednesday, May 10, 2017

Apple Developer

Today is an important date for me. I just applied my Apple Developer from Apple web site. Actually I have been Apple Developer for long time, but I have not paid my annual fee as former developer yet. Even so, I have been doing development since the start of iPhone released. Now my app is ready for Apple Store.

The application process is very simple. First, submit my request from the web site. I applied as an company. What I need to get D&B's DUNS number for my company. This can be obtained for free from D&B Canada. Normally it requires 30 days to process. Another requirement is an email. The email cannot be gmail, hotmail, yahoo, or the likes. The recommended is email with company's domain name. I found that iCloud email is acceptable.

After submitting my request, I receive an email about acceptance. The next step is to agree Apple Developer Program License Agreement.

The last step is to pay my annual fee $99US or $119CAD, plus tax 5.95.

Within one hour after my annual fee payment, I am not registered developer for all Apple platform apps. The first three things I have to do are prompt when I login to my developer's account:


  • Connect to my team members (none so far)
  • Get Certificates which will be used for my apps
  • and set up iTunes connect account to manage my apps,


References



Read More...

Monday, May 08, 2017

Workspace in Xcode

One of interesting things I learned from Developing Apps for iOS CS193P, by Stanford U, is using Workspace in Xcode. This was explained in detail in lecture 9, TableView, at about 46minute.



Follow the instruction, what I did in my app project is to convert my project to Workspace from menu File-Save as Workspace...

Then from Finder to locate another project file and drag it to the Workspace, as two parallel projects.

One of project is a iOS Target type. This target has to be added to another project as embedded binary in project. This can be done by dragging the target to project settings.

The advantage of Workspace is that I can modify both project if needed.

Read More...

Thursday, May 04, 2017

Xcode and Swift Tips and Tricks

During my development of my iOS app, I have encountered some hurdles. Even though some of them are small ones, I did spend a lots of time to find solution to overcome them. Here are some in my past short period.

Can't find customized class from Storyboard


Normally customized view controller classes are used to handle specific requirement for some views. In Storyboard, this customized class can be specified in Storyboard right property panel "Show the identity inspector" tab.

For whatever reason, I may pressed space bar by chance in the area of Module. This caused the Module's value as None! As a result, I got this run time error:

Could not cast value of type 'UIViewController' (0x113f1b798) to 'MyProject.MyViewController' (0x113985200).

I spent hours trying to figure out why. Eventually, I found out the simple solution: change the module to my project.

This is what I had in my Storyboard for this customized class setting:



Hide Tabbar and use toolbar


In a tabar driven app, sometimes, I may need to hide tabbar and show a toolbar as alternative. To hide tabar for next view controller, it can be done in prepare(for segue: sender:) event.

  1. override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
  2.  ...
  3.  let vc = segue.destination
  4.  // call vc's hidebottombar
  5.  vc.hidesBottomBarWhenPushed = true
  6.  ...
  7. }

For the case of normal view controller, bar button item can be directly added to the bottom of the view. For the case of tableview controller, in order to show bar button item on the bottom, a toolbar has to be used to encapsulate bar button items. This can be done in storyboard.

However, it seems that there is no API or method to let vc to show or hide toolbar. At first, I found a solution to show or hide toolbar by adjusting toolbar y position in viewWillAppear event. The problem is that if user changes device from portrait to landscape, the toolbar will be off screen, disappeared. As a result, I have to adjust toolbar y position in the event of viewRotated.

To adjust toolbar y position, I add the following API to view controller as extension. This makes it easier in call this API to show toolbar.

  1. extension UIViewController {
  2.  func setToolBarShow(show: Bool, delay: Double = 2) {
  3.    if let toolbar = self.navigationController?.toolbar {
  4.      let newOriginY = UIScreen.main.bounds.height - toolbar.bounds.size.height
  5.      if toolbar.frame.origin.y != newOriginY {
  6.        toolbar.frame.origin.y = newOriginY
  7.      }
  8.      if delay > 0 {
  9.        // Make sure origin is set correctly
  10.        DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
  11.          if toolbar.frame.origin.y != newOriginY {
  12.            toolbar.frame.origin.y = newOriginY
  13.          }
  14.        }
  15.      }
  16.    }
  17.  }
  18. ...
  19. }

Here the trick to show toolbar in the events of viewDidAppeared and viewRotated is to delay adjusting toolbar y position. It seems that in both events, without delay, toolbar would not show. It may be something inside UIKit would not seeing this adjustment. With delay, the toolbar would show correctly at the bottom of the view.

Change navigation back button's title


In the case of parent VC to child VC by using navigation controller, the top-left button is used to pop off child VC and back to parent VC. The title of this button is by default the title of the parent VC. If the parent title is too long, it may make top text too crowded if the title of child VC is too long. One simple way to change top-left button title to "Back". This can be done by clearing parent title before pushing to child VC. UIKit will automatically use "Back" as the title.

Here is the solution to do that: clear view's title when pushing a new view controller. This can be done in the event of prepare() for segue.

One thing to remember is that to set view's title on the event of viewDidAppear(), otherwise, the view's title would be blank if the view is pushed back.

Resources


Read More...

Friday, April 28, 2017

Custom Store URL for CoreData

Recently I watched Developing iOS Apps with Swift by Stanford U, which was released in iTunes U on Jan 24, 2017. Even this course is for beginners, I still found many new concepts about iOS 10. One of the most interesting thing is about CoreData.

I tried to incorporate the new strategy strongly recommend by Paul Hegarty (instructor) in my App. Soon I realized that many new classes or methods by this strategy are only for devices in iOS 10.*. My app is for pre iOS 10 as well. After some consideration, I decided to use this strategy anyway. For pre iOS 10 cases, I'll continue to use UIManagedDocument to load CoreData database.

My app uses a customized store URL for loading data from CoreData database. The database is located in app's Documents folder. I added the new strategy into my project and tried to use the same URL to load database. To my surprise, my previous database are gone when I run the project in Simulator.

After deep investigation into where the SQLite database is, I found that the URL used by UIManagedDocument is actually pointing to the SQLite database two levels of directories down.



In above example, the URL by UIManagedDocument is defaultDatabase, but the SQLite database is persistentStore, under the directory of defaultDatabase/storeContent. However, the URL used by the new strategy, i.e., NSPersistentContainer, is the URL directly pointing to the SQLite database, persistentStore.

Actually, the first time I tried to load my database by previous URL caused my project crashing. As I discovered above, the URL pointing to defaultDatabase, which is a folder name.

This presents an issue for my app. Some users's device may be pre iOS 10. If they update their device to iOS 10.*, my app has to be able to adjust the previous URL to the correct database, so that users would not lose their data.

After some changes, my app can deal with this transition smoothly without losing their data.

This is a very good experience, incorporating new and efficient strategies into my app and dealing with prior iOS 10 devices.

References


Read More...