728x90
오픈소스 라이브러리를 만들어 볼까 한다.
내용은 안드로이드를 개발한 뒤 iOS를 개발하면서 없어서 불편했던 위젯이나 기능들을 위주로 개발하려고 한다.
유용하고 쓸모있고 없고를 떠나서 오픈소스를 만들어 보겠다는 마음이 중요한 것 아니겠나?!
(아니면 말고,,,)
먼저 개발해보려 간단하게 생각했던건
- Toast
- CheckBox
- RatingStar
- radio button
- radio group
- floating action button
이정도 이다.
iOS 개발은 해왔지만 오픈소스 라이브러리를 개발 하기 위해 먼저 필요한 지식을 학습하고 정리했다.
야곰 닷넷의 "오픈소시 라이브러리" 튜토리얼을 참고했다.
오픈소스란
- 소스코드를 공개해 누구나 특별한 제한 없이 코드를 볼 수 있도록 한 소스코드
- iOS 오픈소스 예시
오픈소스 제작의 의미
- 코드 공개 --> 전 세계인에게 코드리뷰를 받을 수 있다. --> 더 신경쓰고 고민해서 코드를 짜게됨
- 주니어 개발자에겐 색다른 경력이 될 수 있음
- 성장의 씨앗(즐거울 일만 가득할것)
- 실무에서 모듈을 어떻게 더 분리해 볼까 고민하는 내 자신
의존성 관리도구
- 외부 라이브러리를 사용할 때 프로젝트와 해당 라이브러리의 상관관계를 용이하게 관리해 주는 도구
- Java : Maven
- Javasript : Yarn, NPM
- Cocoa (Touch) : Cocoapods, Carthage, Swift Package Manager
- 이러한 도구 없이는 외부 라이브러리를 직접 프로젝트에 포팅해야한다. --> 공수가 많이 든다.
- 시간절약 + 안정성 보장
오픈소스 작성시 주의할 점
- 라이센스!
- MIT : 이 소프트웨어를 누구라도 무상으로 제한없이 취급해도 좋다
- 단 저작권 표시 및 이 허가 표시를 소프트웨어의 모든 복제물 또는 중요한 부분에 기재해야 한다.
- 저자 또는 저작권자는 소프트웨어에 관해서 아무런 책임을 지지 않는다.
- 타 프로그래머가 내 라이브러리의 모듈 내부의 코드를 어느 수준까지 사용하게 할지 생각해야함
- [접근제어 참고자료]
코코아팟이란
- Swift, Objective-C 언어환경 프로젝트의 의존성 관리 도구
- 7만개 이상 라이브러리 보유
- 300만개 이상의 에플리케이션에서 코코아팟 활용중
- 사용법은 인터넷 찾아보면 자세하게 나옴
코코아팟 라이브러리 만들기
- 라이브러리를 만들고자 하는 디렉토리로 이동한다
- 코코아팟 프로젝트를 생성한다.
pod lib create `YOUR_LIBRARY_NAME`
라이브러리 프로젝트 생성시 묻는 질문
- What platform do you want to use?? : iOS
- What language do you want to use?? : Swift
- Would you like to include edmo application with your library? :YES
(이 라이브러리에 대한 화면 스크린샷이 필요하면 YES 를 고른다) - Which testing frameworks will you use?? None
(None 할 경우 Apple 의 XCTest를 사용하면 된다.) - Would you like t odo view based testing ?? No
(Yes 할 경우 페이스북 스냅샷 기반 테스트 오픈소스 FBSnapShot TestCase 포함해줌)
gimtaehyeong-ui-MacBookPro:opensourceTutorial kimtaehyeong$ pod lib create SimpleAlert
Cloning `https://github.com/CocoaPods/pod-template.git` into `SimpleAlert`.
Configuring SimpleAlert template.
------------------------------
To get you started we need to ask a few questions, this should only take a minute.
2020-04-18 02:22:12.007 defaults[22714:3598137]
The domain/default pair of (org.cocoapods.pod-template, HasRunBefore) does not exist
If this is your first time we recommend running through with the guide:
- https://guides.cocoapods.org/making/using-pod-lib-create.html
( hold cmd and double click links to open in a browser. )
Press return to continue.
What platform do you want to use?? [ iOS / macOS ]
> iOS
What language do you want to use?? [ Swift / ObjC ]
> Swift
Would you like to include a demo application with your library? [ Yes / No ]
> Yes
Which testing frameworks will you use? [ Quick / None ]
> None
Would you like to do view based testing? [ Yes / No ]
> ㅜNo
Running pod install on your new library.
Analyzing dependencies
Downloading dependencies
Installing SimpleAlert (0.1.0)
Generating Pods project
Integrating client project
[!] Please close any current Xcode sessions and use `SimpleAlert.xcworkspace` for this project from now on.
Pod installation complete! There is 1 dependency from the Podfile and 1 total pod installed.
[!] Automatically assigning platform `iOS` with version `9.3` on target `SimpleAlert_Example` because no platform was specified. Please specify a platform for this target in your Podfile. See `https://guides.cocoapods.org/syntax/podfile.html#platform`.
Ace! you're ready to go!
We will start you off by opening your project in Xcode
open 'SimpleAlert/Example/SimpleAlert.xcworkspace'
To learn more about the template see `https://github.com/CocoaPods/pod-template.git`.
To learn more about creating a new pod, see `https://guides.cocoapods.org/making/making-a-cocoapod`.
프로젝트가 후다닥 만들어 졌다.
podspec
- 라이브러리에 대한 정보를 담고 있다.
- 소스를 가져와야 하는곳
- 사용할 파일
- 적용할 빌드 설정
- 이름
- 버전
- 라이브러리에 대한 설명
- 일반적인 메타데이터
- 기본 항목
- name
- version
- license
- homepage
- author
- summary
- source
- source_files
- frameworks
- [자세한건 여길 참고]
이렇게 생겼다.
#
# Be sure to run `pod lib lint SimpleAlert.podspec' to ensure this is a
# valid spec before submitting.
#
# Any lines starting with a # are optional, but their use is encouraged
# To learn more about a Podspec see https://guides.cocoapods.org/syntax/podspec.html
#
Pod::Spec.new do |s|
s.name = 'SimpleAlert'
s.version = '0.1.0'
s.summary = 'A short description of SimpleAlert.'
# This description is used to generate tags and improve search results.
# * Think: What does it do? Why did you write it? What is the focus?
# * Try to keep it short, snappy and to the point.
# * Write the description between the DESC delimiters below.
# * Finally, don't worry about the indent, CocoaPods strips it!
s.description = <<-DESC
This library will be used for cocoapods guide
DESC
s.homepage = 'https://github.com/uuzaza@naver.com/SimpleAlert'
# s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2'
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.author = { 'haningya' => 'uuzaza@naver.com' }
s.source = { :git => 'https://github.com/uuzaza@naver.com/SimpleAlert.git', :tag => s.version.to_s }
s.social_media_url = 'haningya.tistory.com'
s.ios.deployment_target = '13.0'
s.source_files = 'SimpleAlert/Classes/**/*'
s.frameworks = 'UIKit'
s.resource_bundles = {
'SimpleAlert' => ['SimpleAlert/Assets/*.png']
}
# s.public_header_files = 'Pod/Classes/**/*.h'
# s.frameworks = 'UIKit', 'MapKit'
# s.dependency 'AFNetworking', '~> 2.3'
end
Github에 저장소를 생성한다.
remte repo 에 프로젝트를 업로드 한다.
gimtaehyeong-ui-MacBookPro:opensourceTutorial kimtaehyeong$ cd SimpleAlert/
gimtaehyeong-ui-MacBookPro:SimpleAlert kimtaehyeong$ ls
Example README.md SimpleAlert.podspec
LICENSE SimpleAlert _Pods.xcodeproj
gimtaehyeong-ui-MacBookPro:SimpleAlert kimtaehyeong$ git remote add origin https://github.com/KimTaeHyeong17/SimpleAlert.git
gimtaehyeong-ui-MacBookPro:SimpleAlert kimtaehyeong$ git push -u origin master
Enumerating objects: 34, done.
Counting objects: 100% (34/34), done.
Delta compression using up to 12 threads
Compressing objects: 100% (28/28), done.
Writing objects: 100% (34/34), 13.57 KiB | 3.39 MiB/s, done.
Total 34 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1), done.
To https://github.com/KimTaeHyeong17/SimpleAlert.git
* [new branch] master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.
오오오 항상 라이브러리 쓰기만 해봤는데 신기하다.
이제 본격적으로 라이브러리 만들어 보잣
그전에 프로젝트 구성을 보면
- SimpleAlert 프로젝트와 Pods 프로젝트로 나뉨
- SimpleAlert 프로젝트 하위의 Example for SimpleAlert 는 데모 애플리케이션 구현하는 영역
(라이브러리 사용 입장에서 테스트) - 개발하는 곳은 ReplaceMe.Swift 파일임(친절함)
*접근 제어자
- open
- public
- internal(기본값)
- fileprivate
- private
- (열린마음) open -> public -> internal -> fileprivate -> private (제한적)
예제 Alert 코드
import UIKit
@available(iOS 13.0, *)
open class YYSimpleAlert: UIView {
private var contentView: UIView!
private var titleLabel: UILabel!
private var lineView: UIView!
private var confirmButton: UIButton!
private var titleText: String?
private var confirmText: String?
private var completion: (() -> Void)?
public convenience init(title: String, confirm: String, completion: (() -> Void)?) {
self.init(frame: CGRect.zero)
self.titleText = title
self.confirmText = confirm
self.completion = completion
}
override public init(frame: CGRect) {
super.init(frame: frame)
contentView = UIView()
titleLabel = UILabel()
lineView = UIView()
confirmButton = UIButton(type: .custom)
self.translatesAutoresizingMaskIntoConstraints = false
contentView.translatesAutoresizingMaskIntoConstraints = false
titleLabel.translatesAutoresizingMaskIntoConstraints = false
lineView.translatesAutoresizingMaskIntoConstraints = false
confirmButton.translatesAutoresizingMaskIntoConstraints = false
}
required public init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
open func setAttribute() {
self.backgroundColor = UIColor.black.withAlphaComponent(0.7)
contentView.layer.cornerRadius = 14.0
contentView.backgroundColor = .white
lineView.backgroundColor = .lightGray
titleLabel.text = titleText ?? "Title"
confirmButton.setTitle(confirmText ?? "confirm", for: .normal)
confirmButton.setTitleColor(.blue, for: .normal)
confirmButton.addTarget(self, action: #selector(confirmAction), for: .touchUpInside)
}
open func show(in superview: UIView) {
setAttribute()
superview.addSubview(self)
self.topAnchor.constraint(equalTo: superview.topAnchor).isActive = true
self.leadingAnchor.constraint(equalTo: superview.leadingAnchor).isActive = true
self.trailingAnchor.constraint(equalTo: superview.trailingAnchor).isActive = true
self.bottomAnchor.constraint(equalTo: superview.bottomAnchor).isActive = true
self.addSubview(contentView)
contentView.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
contentView.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
contentView.heightAnchor.constraint(equalToConstant: 150.0).isActive = true
contentView.widthAnchor.constraint(equalToConstant: 270.0).isActive = true
contentView.addSubview(titleLabel)
titleLabel.centerXAnchor.constraint(equalTo: contentView.centerXAnchor).isActive = true
titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 50.0).isActive = true
contentView.addSubview(lineView)
lineView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true
lineView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true
lineView.heightAnchor.constraint(equalToConstant: 0.5).isActive = true
contentView.addSubview(confirmButton)
confirmButton.topAnchor.constraint(equalTo: lineView.bottomAnchor).isActive = true
confirmButton.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true
confirmButton.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true
confirmButton.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
confirmButton.heightAnchor.constraint(equalToConstant: 44.0).isActive = true
}
@objc
private func confirmAction() {
self.removeFromSuperview()
completion?()
}
}
테스트 할 수 있는 Example for SimpleAlert 에서 사용해 보면
//
// ViewController.swift
// SimpleAlert
//
// Created by uuzaza@naver.com on 04/18/2020.
// Copyright (c) 2020 uuzaza@naver.com. All rights reserved.
//
import UIKit
import SimpleAlert
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func actionAlert(_ sender: Any) {
if #available(iOS 13.0, *) {
YYSimpleAlert(title: "와 이게 되네", confirm: "확인버튼도 커스텀할 수 있네") {
print("completion handler 까지!?!")
}.show(in: self.view)
} else {
// Fallback on earlier versions
}
}
}
잘된닷!!
코코아팟 라이브러리 배포하기
- .podspec을 검사해야 한다!
pod spec lint
- 검증에 실패 할 경우 빨간색 글씨로 알려준다.
- 설명이 충분하지 못하다
- URL 에 접속할수가 없다
- haningya.tistory.com을 validate 하는데 문제가 있다 --> https://haningya.tistory.com/으로 수정한다.
- error! git repo 에 접근할 수 없다?? --> 왜죠 --> 원격 저장소에 버전 태그가 없어서 생긴다고 하신다.
- 아니 내 에러는 그게 아니다. github 주소가 잘못됫으니 spec 을 고쳐뿐다
[github - tag 처음 사용해봤다]
gimtaehyeong-ui-MacBookPro:SimpleAlert kimtaehyeong$ git tag 0.1.0
gimtaehyeong-ui-MacBookPro:SimpleAlert kimtaehyeong$ git push origin 0.1.0
Total 0 (delta 0), reused 0 (delta 0)
To https://github.com/KimTaeHyeong17/SimpleAlert.git
* [new tag] 0.1.0 -> 0.1.0
gimtaehyeong-ui-MacBookPro:SimpleAlert kimtaehyeong$
요로코롬 태그를 달아준다.
아앗
누가 SimpleAlert 라는 pod를 이미 만들었나보다... 이름좀 특이하게 할껄 그랬다.
만약 배포가 완료되면 github 레포에 pod 뱃지가 활성화 된다.ㅎㅎ
코코아팟 라이브러리 튜토리얼은 여기서 끝 이제 내 라이브러리를 만들어 볼 차례다.
좋은 튜토리얼 만들어 주셔서 감사합니다 :) follow 하고 가겠습니닷
728x90
'iOS' 카테고리의 다른 글
GCD : Grand Central Dispatch (0) | 2020.06.16 |
---|---|
WWDC Swift Student Challenge 세팅 (0) | 2020.05.06 |
뱅크 샐러드는 어떤 라이브러리를 쓸까?(iOS 유용한 라이브러리) (0) | 2020.04.04 |
재사용 가능한 UIView를 만들어 보자! (1) | 2020.04.03 |
TheCatAPI를 이용한 Alamofire 예제 (2) | 2020.03.30 |
댓글