//在其他func中呼叫setNeedsUpdateConstraints(在這以layoutSubviews為例)
override func layoutSubviews() {
setNeedsUpdateConstraints()
}
//把你要做的調整放在updateConstraints中
override func updateConstraints() {
textViewWidthConstraint.constant = scrollView.frame.width - imageViewWidthConstraint.constant
super.updateConstraints()
}
2015年6月17日 星期三
調整scrollView的內容位置到目前的textView的位置
func fitScrollView(shouldMove: Bool) {
if let scrollView = scrollView {
var frame = inputTextField.frame
var newSize = inputTextField.sizeThatFits(CGSizeMake(frame.width, CGFloat.max))
frame.size.height = inputTextField.contentSize.height
textViewHeightConstraint.constant = newSize.height
textViewWidthConstraint.constant = scrollView.frame.width - imageViewWidthConstraint.constant
let cursorPosition = inputTextField.caretRectForPosition(inputTextField.selectedTextRange?.start).origin
if cursorPosition.y.isInfinite {
var offset = inputTextField.frame.origin.y - scrollView.frame.size.height + newSize.height
if offset > 0 {
if shouldMove {
scrollView.setContentOffset(CGPointMake(0, offset), animated: true)
} else {
scrollView.setContentOffset(CGPointMake(0, 0), animated: true)
}
}
}
}
}
if let scrollView = scrollView {
var frame = inputTextField.frame
var newSize = inputTextField.sizeThatFits(CGSizeMake(frame.width, CGFloat.max))
frame.size.height = inputTextField.contentSize.height
textViewHeightConstraint.constant = newSize.height
textViewWidthConstraint.constant = scrollView.frame.width - imageViewWidthConstraint.constant
let cursorPosition = inputTextField.caretRectForPosition(inputTextField.selectedTextRange?.start).origin
if cursorPosition.y.isInfinite {
var offset = inputTextField.frame.origin.y - scrollView.frame.size.height + newSize.height
if offset > 0 {
if shouldMove {
scrollView.setContentOffset(CGPointMake(0, offset), animated: true)
} else {
scrollView.setContentOffset(CGPointMake(0, 0), animated: true)
}
}
}
}
}
2015年6月10日 星期三
抓到目前遊標(cursor)的位置
let cursorPosition = self.inputTextField.caretRectForPosition(self.inputTextField.selectedTextRange?.start).origin
println("x:\(cursorPosition.x) y:\(cursorPosition.y)")
2015年5月30日 星期六
podfile的版號表達方式
Besides no version, or a specific one, it is also possible to use logical operators:
'> 0.1'Any version higher than 0.1 超過0.1'>= 0.1'Version 0.1 and any higher version 0.1以上'< 0.1'Any version lower than 0.1 未滿0.1'<= 0.1'Version 0.1 and any lower version 0.1以下
~>:'~> 0.1.2'Version 0.1.2 and the versions up to 0.2, not including 0.2 and higher 0.2以下(不含0.2),0.1.2以上(含0.1.2)'~> 0.1'Version 0.1 and the versions up to 1.0, not including 1.0 and higher 1.0以下(不含1.0),0.1以上(含0.1)'~> 0'Version 0 and higher, this is basically the same as not having it. 0以上(跟沒設定一樣)
2015年5月29日 星期五
簡單整合原生的Camera拍照功能(swift)
要先在class宣告中加入下列兩個Delegate
UIImagePickerControllerDelegate, UINavigationControllerDelegate
在你要用來trigger的function中寫
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera) {
var cameraCaptureController = UIImagePickerController()
cameraCaptureController.delegate = self
cameraCaptureController.allowsEditing = true
cameraCaptureController.sourceType = UIImagePickerControllerSourceType.Camera
self.yourParentViewController?.presentViewController(cameraCaptureController, animated: true, completion: nil)
}
最後再實作你的Delegate
//MARK: UIImagePickerControllerDelegate, UINavigationControllerDelegate
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) {
dismissCameraCaptureController(picker)
//TODO: Pick camera capture here
if let chosenImage = info[UIImagePickerControllerEditedImage] as? UIImage {
//TODO: use chosenImage here
} else {
//TODO: Alert no picture selected.
}
}
func imagePickerControllerDidCancel(picker: UIImagePickerController) {
dismissCameraCaptureController(picker)
}
private func dismissCameraCaptureController(picker: UIImagePickerController) {
picker.dismissViewControllerAnimated(true) { }
}
2015年5月15日 星期五
一些設計原則
//global variable class 存取原則
- 最好以某個專門負責的class(例如,web api)來作為唯一的修改點,其他地方都直接唯讀取用。
- 如果是要存放修改點在其他class的變數,則要另外設local variable在修改完成後再直接copy過去
- 如果不得已非要多方存取與修改時,則要設為synchonize以免在存取的中途被修改。
//TableViewCell 設定原則
- 不要用同一種cell去換成新的UI style
- 要針對各種不用的style去設計不同的cell來用
- 用在viewController決定你要用什麼cell,把style obj傳入tableView中
//集合元素的設計原則
- 不要在多對一之後,再一對多
- 要把多個物件加入在同一個集合元素時,先把多組key統一整理成同一個唯一碼,再用這組唯一碼來還原為一對多。
//儘量避免函數副作用
- side effects是有特別定義的,在IT中專指你的function會對呼叫它的地方造成影響。
- 例如,函數被呼叫時會改動到全域變數,或是你用了inout參數,讓你的function可以直接改動它的輸入參數。
- 比較好的作法
- 儘量少用沒有參數的函數,因為這通常代表它會改動到全域變數。
- 儘量讓每個函數都只實作輸入參數跟輸出之前轉換的邏輯。
//在swift 2.0之後,應該要優先使用struct和enum,需要繼承的時候再用class
- swift 強化了struct和enum的功能,可以實踐class的大部份功用。
- 原來的root class也可以用protocol加上protocol extension來實踐
- 特別是要用RxSwift的時候,因為會用到大量的closure,struct可以確保線程安全。
//用struct的時候不要用到mutating來宣告function
- swift的實作上struct的self物件是immutable的,所以如果你用了mutating,它會幫你再包一層操作,最後還是把你輸入的修改值重新new一個新的instance給你。
//RxSwift設計原則:如果可以,就別在viewModel中用subscribe
- There are ideally no Variables, Subjects ....
- There are no subscribe, bind, drive methods or subscriptions being made in any way.
- Everything is just a definition.
- Because there are no subscriptions, there are no DisposeBags, etc .., no resource management is needed because all operators are already chaining disposing mechanism.
- Everything is decoupled from the UI, there are no UIElements there, only pure logic
2015年5月12日 星期二
訂閱:
文章 (Atom)