Tuesday, 3 March 2020

Force to open a ViewController in particular orientation

Even for the app that only enabled Portrait for Device Orientation in General tab.

Make the viewController to be open in landscape override the following properties.


However, it changes the orientation of the presetingViewController. One solution to force the presetingViewController still in portrait is adding the following properties.





Tuesday, 2 July 2019

Dependency Visualizer

My Fork: 
https://github.com/Sylvia-YiyinShen/objc-dependency-visualizer

A dependency visualisation tool for objective-c/Swift project.

Example:


The above graph describe a relation between ViewController and MainViewModel: ViewController just holds a reference of MainViewModel.

If we initialise MainViewModel within ViewController as below,  check how different the graph would be:






Other visualisation tools:
https://github.com/Sumolari/swift-relationship-graph

Monday, 10 June 2019

New in Swift iOS 13

Improved Performance

  • 0% Launch time overhead with Swift 5
  • 15% Smaller Code Size when using ‘Optimize for Size’
  • Faster Bridging Between Swift and Objective-C. Improved string interoperability. 1.6X faster NSDictionary to Dictionary Bridging. 15X faster NSString operations when performed on bridged Swift Strings.



SwiftUI
  • Build user interfaces across all Apple platforms
  • Improved LocalizedString Interpolation. SwiftUI supports formatted LocalizedString better




Friday, 31 May 2019

String Localization in Xcode

Check example code
https://github.com/Sylvia-YiyinShen/LocalisationExample

Prep work

In Project Info Panel add a language.



Storyboad localization

XCode will prompt to ask you to choose the files/storyboard for localization.
Tap finish, now you should be able to see XCode has generated storyboard.strings for you as below


At the moment it is empty, let's add  label in Main.storyboard
And in File Inspector, un-select the language then select again

Now you should see XCode updated the Main.strings file as


Change the labels to another language.
Edit the scheme by 


Build and re-run, you should see the translated labels.


XCode provides another way to preview the storyboard
You can change the .strings file to a Interface Build Storyboard


Click the converted .storyboard



XIB Localization

However, you will find other XIB outside of any storyboard has not been localized yet, even those existed before you turn on localization. XCode didn't automatically prepare localization for you and even didn't ask you to choose.

Just select XIB, go to File Inspector, and select the language under Localization section.  Similarly, you can choose to convert it to .string or .xib file.



Localize Strings Generated in Code

If you decided to utilize localization at the very beginning, you could create a string file via File -> New -> File

Specify the text in .strings file


Use the localized string


tableName should be the .strings file name



Prepare you strings for Localization

If you don't want localization for now but want to make your strings ready for future requirements.



One day, you want to turn on Localization, select the project, XCode -> Editor -> Export For Localization, XCode will generate a Localizable.strings file contains those strings created via NSLocalizedString(key, comment) along with any other storyboards or XIBs that have been selected localization. Update those exported files, you can choose XCode ->Edit -> Import or just drag the Localizable.strings file into your project.

Drag the file here and link it into XCode, choose the language from Edit Scherme, build and rerun, you should be able to see the transalted texts.





Sunday, 26 May 2019

Introduction to State Machine for IOS App

Demo:
https://github.com/Sylvia-YiyinShen/StateMachineDemo


Why State Machine pattern? What we want to achieve? What are the benefits introducing State Machine?

 1. We want to define rules of transition, final state if needed to end the transitions as well. Un-allowed transitions can be stopped at compiling stage.
 2. Since there might be more than one state machines within the whole app, we want to control the existence of state machines(lifecycle of modules).E.g we have SignIn and MainWorkflow state machines, MainWorkflow should not exist until login state has been entered.


 Prototyping process

 1. For each module, we want to define several states, enum is a good choice.
 2. Each state machine is responsible for a single set of states enum, however we hope the state machine class can be reused, so we have to make enums conform to one struct/class.
 3. For each state, we want to maintain the allowed transitions which has to be stored property. Since enum does not support store properties, we need a wrapper struct/class of state enum. So we need the help of Generics.

 protocol StateIdentifier
 class State<T> where T: StateIdentifier
 class StateMachine<T> where T: StateIdentifier


 In this example, we will have two state sets and accordingly two state machines

 enum SignInState: StateIdentifier
 enum MainWorkflowState: StateIdentifier

 For simplicity, state machines initialisation and configuration are handled in the view controller, ideally we can put in an appCoordinator-like role.

 Check configureStateMachine() in ViewController.swift. The configuration requires
 1. Initialize the states along with the transition rules
 2. Configure state.didEnter .willExit
 3. Initialize a state machine with the above states injected

 In this simple demo, I am just using a label to indicate where we are at.
 Play around the buttons to see how the main workflow module is blocked by sign in/out state.

By introducing state machine, regardless of the messy buggy or wrong routing logic, we will never break the transition rules we've set up.

Saturday, 25 May 2019

Debugging Tricks

Let's look at several debugging tricks,  especially helpful when you just joined a team facing with the large and unfamiliar codebase

Quickly find the ViewController that has been pushed along with the line in code.

Go to the Breakpoint Navigator of the left panel in  XCode
Click the + button on left bottom, choose Symbolic Breakpoint,
Add the objective-c function signature in Symbol


Disable the breakpoint and enable it just before the interaction triggers pushing that viewController.
XCode will pause the execution at the [UINavigationController pushViewController:animated:] and you will find the exact line in project in Debug Navigator just below [UINavigationController pushViewController:animated:]



Another way to find the name of ViewController or sub UIView/UIViewController
Show the Debug area, build and run, tap the Debug View Hierarchy button on the debug menu bar
Select the view controller or any UI element you want to know and check its name at the top 





LLDM commands

po to print


expression to change values at runtime without changing code and re-run


jump to skin without comment out and re-run

Edit breakpoint to put expression in Action
It also allows to continue automatically



Watch values changes, XCode will pause every time the values has been changed

Thursday, 16 May 2019

Go Concurrency Patterns

Great materials to go through
https://talks.golang.org/2012/concurrency.slide
https://talks.golang.org/2013/advconc.slide

Check my reorganised code at Github https://github.com/Sylvia-YiyinShen/GolangConcurrency

  • Channels allows two goroutines to communicate
  • Select provides a switch-like way to handle multiple channels instead of multiple goroutines
  • time.After to block
  • Quit via Select

Pulldown Refresh Demo

Check source code at Github:
https://github.com/Sylvia-YiyinShen/PulldownRefreshDemo

There are several different ways to implement pull-down refresh. One is based on scrollView delegate functions, another one is based on key-value observing on contentOffset. My demo is implemented via the later approach, since when applying the pull-down refreshing to a tableVIew it just requires 2-line changes.



How to use
  • Grab Indicator and PulldownRefresh folder to your project
  • Make your tableView subclassing RefreshableTableView
  • Invoke RefreshableTableView func configureRefreshControl(refreshHandler: @escaping () -> Void)
  • Invoke in the right place RefreshableTableView  func refreshDone()


Note: Look at the RefreshableTableView.swift if you also want to apply refreshControl to CollectionView


Wednesday, 15 May 2019

Start Learning Golang

Compressed Golang Basics
https://github.com/Sylvia-YiyinShen/GolangBasics

Go Tutorial
https://tour.golang.org

Go Documentation
https://golang.org/doc/

Go Concurrency Model
Go Concurrency Patterns (slides)
Advanced Go Concurrency Patterns (slides)
Share Memory by Communicating

Go Play Space
https://goplay.space/
Install the Go tools

Open and follow the guide 
https://golang.org/doc/install?download=go1.12.5.darwin-amd64.pkg

Download .pkg and double click to finish the installation
Then follow the guide to check and test if Go is installed correctly
You can pick any location as the go directory

Test if Go installed correctly
Create a xxx.go file
go build
./xxx

GO extension in VS Code
https://marketplace.visualstudio.com/items?itemName=ms-vscode.Go