Macで立てたlocalhostサーバーにiPhoneからアクセスする
English version below
はじめに
Macでテスト用サーバーを立ててiPhoneから簡易的に試したいときのTipsです。
前提
やりかた
- Mac でLocalhostサーバーを立てる
- localhost:{Port番号}でアクセスできることをsafariなどで確認する
- Mac [共有] からMacにアクセスするためのドメイン名を調べる({YOUR_PC_NAME}.local)
- iPhoneのsafariなどで、ドメイン名({YOUR_PC_NAME}.local)にアクセス
完了です。
注意点1
Mac上のサーバーのポート番号に80番などよく使われるt番号を使用すると、MacのFirewallにインバウンドを拒否されます。
回避方法としては、Mac [環境設定]-[セキュリティ&プライバシー] でFirewallをOFFにすればアクセスできますが、お勧めできません。
注意点2
iOSアプリのAPIサーバーとしてMac のlocalhost サーバーを使用した場合、XcodeでATS(App Transport Security)をOFFにするのを忘れずに。
HTTPSでアクセスできる場合は問題無いです。
iOS Xcode10 で”CommonCrypto”のおかげでビルドエラーが出た時の対処法
English version below
はじめに
Xcode10来ましたね。
早速アップデートしてみると次のようなエラー。
CocoaPodsとかで、モジュールをプロジェクトに組み込んでいると出会いやすいっぽいです。
Redefinition of module "CommonCrypto"
error: could not build Objective-C module 'YOUR_MODULE'
読み進んでみると"CommonCrypto"が再定義されていると。
やったこと
1つ目
クリーンしてビルド
ー>失敗
2つ目
cocoapods pod update を実行
-> だめ
解決方法
対象のModuleに含まれる"CommonCrypto"フォルダを削除する。
どうやらCommonCryptoがXcode10から標準ライブラリに組み込まれるようになったらしいです。
その結果、既存のファイルとコンフリクトが発生、再定義とみなされるようです。
つらい。。。
iOS How to change a language settings while debugging on the devices
Introduction
This article shows how to change a language settings while debugging on the devices.
This method is useful for confirming the localized String or text including line breaks.
It won't need to change the language from settings anymore.
Solution
There are 2 steps for setting the language.
- [Open Edit scheme]
- [Run]-[Application Language]-[System Language] and select a language you want to set.
iOS 実機でデバッグするときに言語設定を変更する
iOS UIPageViewControllerで"Unbalanced calls to begin/end appearance transitions for" が出たときの対処方法
English version below
はじめに
UIPageViewControllerを早送りしたときに次のようなエラーが出ました。
Unbalanced calls to begin/end appearance transitions for
そのときのコードはこんな感じです。
class MyPageViewController: UIPageViewController { var maxPage = 3 var currentPage = 0 ~~~~ // SomeCode.... ~~~~ } extension MyPageViewController: UIPageViewControllerDataSource { func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? { guard self.currentPage > self.maxPage else { return nil } self.currentPage += 1 let myAfterVC = MyAfterViewController() return myAfterVC } func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? { guard self.currentPage >= 0 else { return nil } self.currentPage -= 1 let myBeforeVC = MyBeforeViewController() return myBeforeVC } }
原因
このエラーメッセージは、現在のUIViewControllerの表示が完了する前に、次のUIViewControllerへ遷移しようとしたときに出るようです。
解決方法
遷移中に再度遷移しないようにフラグをもたせました。
UIPageViewControllerDelegateを通して、で遷移の開始と終了を知ることができます。
したがって、コードでは次のようになります。
class MyPageViewController: UIPageViewController { var isTransitioning = false var maxPage = 3 var currentPage = 0 ~~~~ // SomeCode.... ~~~~ } extension MyPageViewController: UIPageViewControllerDataSource { func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? { guard self.currentPage < self.maxPage, self.isTransitioning == false else { return nil } self.currentPage += 1 let myAfterVC = MyAfterViewController() return myAfterVC } func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? { guard self.currentPage >= 0, self.isTransitioning == false else { return nil } self.currentPage -= 1 let myBeforeVC = MyBeforeViewController() return myBeforeVC } } extension MyPageViewController: UIPageViewControllerDelegate { func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) { self.isTransitioning = true } func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) { self.isTransitioning = false } }
iOS UIPageViewController How to soleve the error message "Unbalanced calls to begin/end appearance transitions for" .
Introduction
When I tried to transition some pages so rapidly.
The Xcode shows an error message as below.
Unbalanced calls to begin/end appearance transitions for
The code is below.
class MyPageViewController: UIPageViewController { var maxPage = 3 var currentPage = 0 ~~~~ // SomeCode.... ~~~~ } extension MyPageViewController: UIPageViewControllerDataSource { func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? { guard self.currentPage > self.maxPage else { return nil } self.currentPage += 1 let myAfterVC = MyAfterViewController() return myAfterVC } func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? { guard self.currentPage >= 0 else { return nil } self.currentPage -= 1 let myBeforeVC = MyBeforeViewController() return myBeforeVC } }
Why
This error message is showed up when a new transition begin before an old old is not completed.
Solution
To prepend a new transition before an old one is not completed, I added a transitioning flag in MyPageViewController and change the value in UIPageVieController Delegate.
The true code is below.
class MyPageViewController: UIPageViewController { var isTransitioning = false var maxPage = 3 var currentPage = 0 ~~~~ // SomeCode.... ~~~~ } extension MyPageViewController: UIPageViewControllerDataSource { func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? { guard self.currentPage < self.maxPage, self.isTransitioning == false else { return nil } self.currentPage += 1 let myAfterVC = MyAfterViewController() return myAfterVC } func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? { guard self.currentPage >= 0, self.isTransitioning == false else { return nil } self.currentPage -= 1 let myBeforeVC = MyBeforeViewController() return myBeforeVC } } extension MyPageViewController: UIPageViewControllerDelegate { func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) { self.isTransitioning = true } func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) { self.isTransitioning = false } }
iOS How to set the Autolayout programatically
Introduction
It was difficult and complexity to set the autolayout programatically when the AutoLyaout announced in iOS
NSLayoutConstraint(item: button, attribute: .leading, relatedBy: .equal, toItem: self.view, attribute: .leadingMargin, multiplier: 1.0, constant: 0.0).isActive = true
That was because I used to use Snapkit(OSS).
But, these days, it will easy to set the autolayout programatically.
I'll introduce the method of setting autolayout programatically.
How to set the autolayout programatically
For example, if you want to the view at the bottom of the self.view, you can easy to set it below.
Code
let button = UIButton() self.view.addSubview(button) button.translatesAutoresizingMaskIntoConstraints = false button.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true button.heightAnchor.constraint(equalTo: self.view.heightAnchor, multiplier: 0.06).isActive = true button.widthAnchor.constraint(equalTo: self.view.widthAnchor, multiplier: 0.7).isActive = true button.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: -20).isActive = true
Attention
order to calling the addSubview()
If you register the constraint to self.view before calling addSubview method, the app will crash.
Don't forget setting the translatesAutoresizingMaskIntoConstraints
If you forget to set the translatesAutoresizingMaskIntoConstraints to false, the constraint will not working.
Don't forget setting "isActive = true"
If you forget to set the isActive propery, the constraint will not working.
How to set the autolayout to SafeArea programatically
To set the autolayout to Safeare, you can use safeAreaLayoutGuide.
if #available(iOS 11, *) { button.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor, constant: -20).isActive = true } else { button.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: -20).isActive = true }
How to make a margin related with other view's height by ration.
If you want to set the UIButton at the top of self.view with margin "self.view.frame.size.height * 0.3", you can use the UILayoutGuide.
In programatically autolayout setting, it not need to use UIView for spacer anymore.
let spacer = UILayoutGuide() self.view.addLayoutGuide(spacer) spacer.heightAnchor.constraint(equalTo: self.view.heightAnchor, multiplier: 0.5).isActive = true spacer.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true spacer.topAnchor.constraint(equalTo: button.bottomAnchor).isActive = true
Finally
I'll show the whole code to initialize the UIButton instance and set the autolayout programatically.
lazy var mybutton: UIButton = { let button = UIButton() self.view.addSubview(button) button.translatesAutoresizingMaskIntoConstraints = false button.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true button.heightAnchor.constraint(equalTo: self.view.heightAnchor, multiplier: 0.06).isActive = true button.widthAnchor.constraint(equalTo: self.view.widthAnchor, multiplier: 0.7).isActive = true let spacer = UILayoutGuide() self.view.addLayoutGuide(spacer) spacer.heightAnchor.constraint(equalTo: self.view.heightAnchor, multiplier: 0.5).isActive = true spacer.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true spacer.topAnchor.constraint(equalTo: button.bottomAnchor).isActive = true return button } ()