티스토리 뷰
[1] 용어정리
text selection 하면 나오는 등장하는 메뉴 팝업 UI를
HIG 에서는 Edit Menus 라고 지칭하고
개발 용어로는 UIMenuController 입니다.
그리고 Edit Menu (UIMenuContoller) 안에 나오는 Cut, Copy.. 이런 것들을
Command, Action, MenuItem 이라는 용어로 혼용해서 부릅니다.
[2] UIMenuController 커스터마이징 (1) - System
첫번째로, UIMenuController 에 나오는 system commands 중 원하는 command 만 나오게 커스터마이징 하려면
어떻게 해야할까요?
UIMenuController가 표시되기 전에 UIResponder 의 canPerformAction(_:withSender:) 이 호출됩니다.
이 메소드를 오버라이딩 해서 print 해보면
class CustomTextView: UITextView {
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
print(action)
return super.canPerformAction(action, withSender: sender)
}
}
UIMenuController가 나타나기 전에
canPerformAction(_:withSender:) 이 여러번 호출되고 아래와 같은 action들이 프린트 됩니다.
cut:
copy:
select:
selectAll:
paste:
delete:
_promptForReplace:
_transliterateChinese:
_insertDrawing:
...
이 중, true를 리턴해준 action들만 UIMenuController에 나오게 되는 것입니다.
그래서 system commands 중, 원하는 command (또는 action) 만 나오게 커스터마이징 하고 싶다!!
예를들어 cut 만 나오게 하고싶다!!! 라고 한다면, 이렇게 해주면 되겠죠?
class CustomTextView: UITextView {
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
if action == #selector(cut(_:)) {
return true
} else {
return false
}
}
}
또는 텍스트뷰가 isEditable일 때, Cut은 기본 command 니까 이렇게 해줘도 무방합니다!
class CustomTextView: UITextView {
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
if action == #selector(cut(_:)) {
return super.canPerformAction(action, withSender: sender)
} else {
return false
}
}
}
참고로 아까 출력된 actions들 중, 언더바가 안붙은 action은
UIResponderStandardEditActions 에 정의되어있습니다. (언더바 붙은 action은 어디에 정의되어있는 지 모르겠네요;;)
cut:
copy:
select:
selectAll:
paste:
delete:
_promptForReplace:
_transliterateChinese:
_insertDrawing:
...
UIResponderStandardEditActions 은 '앱이 editing을 지원하기 위해 채택할 수 있는 표준 메소드 모음' 으로,
문서에서 아래와 같이 말하고 있습니다.
"UIMenuController는 UIResponderStandardEditActions 의 메소드들을 호출해서 editing action 을 리포팅한다.
그 다음, UIMenuController는 UIKit에 적절한 메서드를 구현하는 객체를 검색하도록 요청하여
해당 메서드를 구현하는 첫 번째 객체에 대해 메서드를 호출한다."
[3] UIMenuController 커스터마이징 (2) - Custom
두번째로, system command 말고 custom command를 추가하고 싶다면 어떻게 해야할까요?
menuItems 프로퍼티를 사용하면 됩니다.
menuItems의 디폴트값(no custom menu items)은 nil 입니다.
menuItems 를 통해 cutom menu item을 추가하면 system menu item 뒤에 나오게 됩니다.
UIMenuController.shared 로 싱글톤 객체를 가져와서
세팅해보겠습니다.
UIMenuController.shared.menuItems = [
UIMenuItem(title: "안녕", action: #selector(sayHello))
]
@objc
private func sayHello() {
print("hello")
}
맨 뒤에 Custom MenuItem이 잘 추가됩니다.
그리고 만약 Custom MenuItem 만 나오게 하고 싶다고 하면,,
아까 살펴본 것과 동일하게 canPerformAction(_:withSender:) 을 오버라이딩해서 custom behavior 를 추가하시면 됩니다.
[4] UIMenuController의 update 메소드
update() 메소드를 통해 menu items 을 수정하고 이를 force update 를 시킬 수 도 있습니다.
이 메소드가 필요한 사례가 문서에 잘 나와있는데요,
1) pasteboard에 데이터가 없어서 '붙여넣기' 를 비활성화시켜 Edit Menus 를 띄웠다.
2) 근데 pasteboard에 데이터가 생겼다!
3) Edit Menus 를 강제업데이트하자!
이런 상황에서 update를 콜하면 됩니다.
간단한 테스트를 해봅시다.
몇초 후, 아이템을 '안녕' -> '방가'로 바꾸기! with update
update를 하면 Edit Menus가 계속 띄워진 상태를 유지하며 안의 아이템들만 바뀌는 것이 아니라
그냥 닫히는 것이네요!!
닫혀서 사용자가 다시 클릭하면 업데이트된 Edit Menus 를 보여주는 방식입니다.
참고로 만약 update를 안하면
시간이 지나도 계속 '안녕' 으로 남아있으니 위의 방식이 더 좋긴 합니다!
[ 더 보면 좋을 것 ]
https://betterprogramming.pub/uimenucontroller-and-manipulating-the-responder-chain-c06fad73c64b
[ 참고 ]
iOS 16 에 textView(_:editMenuForTextIn:suggestedActions:) 가 추가되었습니다 :-)
'🍏 > iOS' 카테고리의 다른 글
[iOS] DiffableDataSource 헷갈리는 것 정리 (1) | 2022.06.29 |
---|---|
[iOS] UITableViewDiffableDataSource의 4가지 apply 메서드 (0) | 2022.06.28 |
[iOS] RxSwift 로 살펴보는 써드파티 라이브러리 5가지 사용 방법 (0) | 2022.03.12 |
[iOS] Overriding Build Settings for a Target 원복하기 (0) | 2022.02.08 |
[iOS] UICollectionViewCell isSelected iOS 15 이슈 (1) | 2021.12.17 |
- Total
- Today
- Yesterday
- 구글 Geocoding API
- Watch App for iOS App vs Watch App
- 장고 Custom Management Command
- 장고 URL querystring
- Django FCM
- flutter build mode
- flutter 앱 출시
- Flutter Text Gradient
- Django Firebase Cloud Messaging
- SerializerMethodField
- flutter dynamic link
- ipad multitasking
- Flutter Clipboard
- METAL
- ribs
- Python Type Hint
- Flutter 로딩
- cocoapod
- 플러터 싱글톤
- Sketch 누끼
- Dart Factory
- github actions
- drf custom error
- DRF APIException
- Django Heroku Scheduler
- flutter deep link
- 플러터 얼럿
- Flutter Spacer
- Flutter getter setter
- PencilKit
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |