티스토리 뷰
안녕하세요 오늘은 최근 앱 개발을 하며 React Native를 패치(patch) 하여 사용했던 경험을 공유하고자 합니다.
해당 과정은 지난 이슈 포스팅에서 진행했던 방법 중 하나인데요.
Background
IOS는 Input type이 password인 경우에는 비밀번호를 다시 쳤을 때 입력했던 값들이 자동으로 삭제됩니다.
이는 IOS에서 기본으로 설정되어있는 것으로 해당 부분을 수정하려면 native언어를 수정해야 합니다.
관련 이슈를 patch-package라는 라이브러리를 사용하여서 React Native를 패치(patch) 해 보았습니다.
Patch-package Library
Patch-package 라이브러리는 npm 패키지 의존성은 그대로 유지하면서, 변경한 npm 패키지의 내용을 버전 관리 대상으로 간편하게 만들어 줍니다.
이는 node-modules안의 파일들을 커스텀한 상태가 배포 상태에서도 지속되도록 수정사항을 기억해뒀다가 배포 시 node-modules 위에 덮어 씌워주게 되는 방식입니다.
즉, node_modules에 수정한 사항이 git으로 관리되고 어떠한 실행 환경에서도 적용되도록 해줍니다.
라이브러리를 사용하는 방식은 아래와 같습니다.
- node_modules 안의 특정 package의 수정사항을 patch 파일 형태로 patches 아래에 저장한다.
- patches 안의 patch를 node_modules 안에 적용한다.
1. Set-up
설치는 아래와 같이 해주세요
In package.json
"scripts": {
+ "postinstall": "patch-package"
}
patch-package 및 postinstall-postinstall 설치
yarn add patch-package postinstall-postinstall
2. Usage
2-1. NPM 패키지 코드 수정
저는 Stack Of Flow의 솔루션 코드를 참고하여 해당 코드가 있는 NPM Package 경로를 찾아 직접 수정해 주었습니다.
- Path
node_modules/react-native/ // Libraries/Text/TextInput/RCTBackedTextInputDelegateAdapter.m
// node_modules/react-native/
// Libraries/Text/TextInput/RCTBackedTextInputDelegateAdapter.m
- (BOOL)textField:(__unused UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
//Setting the new text.
NSString *updatedString = [textField.text stringByReplacingCharactersInRange:range withString:string];
textField.text = updatedString;
//Setting the cursor at the right place
NSRange selectedRange = NSMakeRange(range.location + string.length, 0);
UITextPosition* from = [textField positionFromPosition:textField.beginningOfDocument offset:selectedRange.location];
UITextPosition* to = [textField positionFromPosition:from offset:selectedRange.length];
textField.selectedTextRange = [textField textRangeFromPosition:from toPosition:to];
//Sending an action
[textField sendActionsForControlEvents:UIControlEventEditingChanged];
return NO;
}
2-2. 수정 코드 패치 파일 생성
package-name을 명시하여 패치파일을 생성해줍니다.
yarn patch-package package-name
yarn patch-package react-native
프로젝트 root 경로에 patches 폴더가 생성된 것을 보실 수 있습니다. 해당 파일 안에서 수정사항이 저장된 것을 확인할 수 있습니다.
이 수정사항들은 Git으로 관리되고, 어떤 환경에서도 적용되도록 보장합니다. 때문에 팀 프로젝트에서도 충돌 없이 유연하게 관리 할 수 있습니다.
diff --git a/node_modules/react-native/Libraries/Text/TextInput/RCTBackedTextInputDelegateAdapter.m b/node_modules/react-native/Libraries/Text/TextInput/RCTBackedTextInputDelegateAdapter.m
index c6c254c..bd842d0 100644
--- a/node_modules/react-native/Libraries/Text/TextInput/RCTBackedTextInputDelegateAdapter.m
+++ b/node_modules/react-native/Libraries/Text/TextInput/RCTBackedTextInputDelegateAdapter.m
@@ -70,32 +70,20 @@ - (void)textFieldDidEndEditing:(__unused UITextField *)textField
- (BOOL)textField:(__unused UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
- NSString *newText =
- [_backedTextInputView.textInputDelegate textInputShouldChangeText:string inRange:range];
+ //Setting the new text.
+ NSString *updatedString = [textField.text stringByReplacingCharactersInRange:range withString:string];
+ textField.text = updatedString;
- if (newText == nil) {
- return NO;
- }
+ //Setting the cursor at the right place
+ NSRange selectedRange = NSMakeRange(range.location + string.length, 0);
+ UITextPosition* from = [textField positionFromPosition:textField.beginningOfDocument offset:selectedRange.location];
+ UITextPosition* to = [textField positionFromPosition:from offset:selectedRange.length];
+ textField.selectedTextRange = [textField textRangeFromPosition:from toPosition:to];
- if ([newText isEqualToString:string]) {
- _textDidChangeIsComing = YES;
- return YES;
- }
-
- NSMutableAttributedString *attributedString = [_backedTextInputView.attributedText mutableCopy];
- [attributedString replaceCharactersInRange:range withString:newText];
- [_backedTextInputView setAttributedText:[attributedString copy]];
+ //Sending an action
+ [textField sendActionsForControlEvents:UIControlEventEditingChanged];
- // Setting selection to the end of the replaced text.
- UITextPosition *position =
- [_backedTextInputView positionFromPosition:_backedTextInputView.beginningOfDocument
- offset:(range.location + newText.length)];
- [_backedTextInputView setSelectedTextRange:[_backedTextInputView textRangeFromPosition:position toPosition:position]
- notifyDelegate:YES];
-
- [self textFieldDidChange];
-
- return NO;
+ return NO;
}
- (BOOL)textFieldShouldReturn:(__unused UITextField *)textField
3. Caution
해당 라이브러리는 패키지 버전이 달라지면 재설정 해주어야 합니다. patch 된 버전과 package.json or yarn.lcok 에 저장된 버전을 확인하고 수동으로 맞춰주시면 됩니다.
4. Test
잘 반영이 되었는지 확인하기 위해 node_modules를 삭제하고 재설치 후 빌드까지 해봅니다.
node_modules 삭제
rm -rf node_modules
node_modules 설치
yarn
Pod 삭제 후 재설치
cd ios
rm -rf Podfile.lock Pods
pod install
yarn ios
Build
yarn ios
Reference
'Frontend > React-native' 카테고리의 다른 글
- Total
- Today
- Yesterday
- 모두를 위한 컴퓨터 과학
- 자바스크립트 클로저
- css
- github
- 자바스크립트 비동기 처리
- 타입스크립트
- React
- 리액트
- 자바스크립트
- 무한스크롤
- 항해99
- html
- 리액트네이티브
- 네트워크
- 실전프로젝트
- cs50
- 프로그래머스
- javascript
- 백준
- network
- React Query
- reactquery
- python
- GIT
- 프로그래머스 자바스크립트
- 클로저
- 자바스크립트알고리즘
- 알고리즘자바스크립트
- 프로그래머스 베스트앨범 자바스크립트
- 모두를위한컴퓨터과학
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |