Programming/iOS
iOS: UIStackView
iOS: UIStackView
2021.08.10์ด๋ฒ์ UI ๊ตฌ์ฑํ๋ฉด์ ์คํ ๋ทฐ๋ฅผ ์ฌ์ฉํ๊ฒ ๋์๋ค. ์ด๋ฏธ ํ ๋ฒ ๋ณธ ๋ด์ฉ์ธ๋ฐ๋, ๋ง์ ๋ค์ ํ๋ ค๋๊น ์ด๋ ต๊ณ , ํท๊ฐ๋ ค์ ๋ค์ ๊ณต๋ถํ๋ฉด์ ๋ด์ฉ์ ์ ๋ฆฌํ๋ค. UIStackView @MainActor class UIStackView: UIView A streamlined interface for laying out a collection of views in either a column or a row. ์ด์ด๋ ํ์ ๋ทฐ ์ปฌ๋ ์
์ ๋ฐฐ์นํ๊ธฐ ์ํ ๊ฐ์ํ๋ ์ธํฐํ์ด์ค์
๋๋ค. ์ฝ๊ฒ ๋งํ๋ฉด, ๊ฐ๋ก๋ ์ธ๋ก๋ก ๋ ์ด์์์ ๋ฐฐ์นํ ๋ ์ฌ์ฉํ๋ค. ์คํ ๋ทฐ ๋ด๋ถ์ ๋ค๋ฅธ ์คํ ๋ทฐ๋ฅผ ์ค์ฒฉํด์ ๋ ๋ณต์กํ ๋ ์ด์์์ ๋ง๋ค ์ ์๋ค. Android์ LinearLayout๊ณผ ์ ์ฌํ๋ค. ์คํ ๋ ์ด์์์ผ๋ก ์ง์ ์ก์์ค ์๋ ์๋ ๊ฑด๋ฐ, ์ด๊ฑธ..
UserDefaults, KeyChain, Core Data
UserDefaults, KeyChain, Core Data
2021.07.23UserDefaults ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ ๋ Info.plist ์ ์ ์ฌํ ๊ตฌ์กฐ๋ก ์ ์ฅํ๋ค. UserDefaults.plist๋ ์ฑ ํด๋ ๋ด์ Library ํด๋์ ์ ์ฅ๋๋ค. ์ ์ฅํ ์ ์๋ ํ์ NSString NSNumber NSData NSArray NSDictionary NSData ์ฌ์ฉ์ ๊ฐ์ฒด๋ฅผ ์ ์ฅํ๋ ค๋ฉด Codable๋ก ๋ง๋ค์ด์ NSData๋ก ๋ณํํด์ ์ ์ฅํ๋ค. ์ต๊ทผ ๊ฒ์ ๋ชฉ๋ก, ์จ๋ณด๋ฉ ์ฌ๋ถ ๋ฑ (๋ณด์์) ๋ฏผ๊ฐํ์ง ์์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ค. ๋ง์ ์์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ธฐ ์ํ ๊ฒ์ด ์๋๋ค! ์ฑ์ด ์์๋ ๋ UserDefaults.plist ํ์ผ์ด ๋ฉ๋ชจ๋ฆฌ์ ๋ก๋๋๋ค. ๊ทธ๋์ ๋ง์ ์์ ๋ฐ์ดํฐ๋ฅผ UserDefaults์ ์ ์ฅํ๋ฉด ์ฑ ์ฑ๋ฅ์ ์๋นํ ์ํฅ์ ๋ฏธ์น ์ ์๋ค. ์ฌ์ฉ์๊ฐ ํ์๊ธฐ ์ฑ์ ์ฌ์ฉํ์ฌ ์ก..
iOS: ์ค๋์ค ๋
น์, ์ฌ์, ์ ์ฅํ๊ธฐ
iOS: ์ค๋์ค ๋ น์, ์ฌ์, ์ ์ฅํ๊ธฐ
2021.07.06๊ฐ์ AVFoundation์ ์ด์ฉํด์ ์ค๋์ค๋ฅผ ๋
น์, ์ฌ์, ์ ์ฅํด๋ณด์. ์ฝ๋๋ฅผ ์์ฑํ๊ธฐ ์ ์ ๋จผ์ AVFoundation ์์ ์ค์์ ์ธ ๊ฐ์ง ํด๋์ค๋ฅผ ์ดํด๋ณธ๋ค. AVAudioSession AVAudioRecorder AVAudioPlayer AVAudioSession class AVAudioSession: NSObject An audio session acts as an intermediary between your app and the operating system—and, in turn, the underlying audio hardware. ์ค๋์ค ์ธ์
์ ์ฑ๊ณผ ์ด์ ์ฒด์ ์ฌ์ด์ ์ค๊ฐ์ ์ญํ ์ ํ๋ฉฐ ๊ธฐ๋ณธ ์ค๋์ค ํ๋์จ์ด ์ญํ ๋ ํฉ๋๋ค. ๋ชจ๋ iOS, tvOS, watchOS ์ฑ์๋ ๋ค์ ๋์์ผ๋ก..
iOS: UIMenu ์ฌ์ฉํด๋ณด๊ธฐ
iOS: UIMenu ์ฌ์ฉํด๋ณด๊ธฐ
2021.06.15Apple์ ๋ฏธ๋ฆฌ ์๋ฆผ ์ฑ ํ๋ฉด์ด๋ค. ๋ด๋น๊ฒ์ด์
์ฐ์ธก ์๋จ ๋ฒํผ์ ํญ ํ๋ฉด ํด๋น ์์น์ ๋ฉ๋ด ๋ชฉ๋ก์ด ๋ํ๋๋ค. ์ง๊ธ ํ๊ณ ์๋ ํ๋ก์ ํธ์ ์ด ๋ฉ๋ด๋ฅผ ์ ์ฉํ๊ณ ์ถ์ด์ ์ฐพ์๋ดค๋๋ฐ, ActionSheet๋ฅผ ์ฌ์ฉํ๋ผ๋ ์๊ธฐ๊ฐ ๋ง์๋ค. ๊ทธ๋์ UIAlertController๋ฅผ ์ฌ์ฉํ๋๋ฐ, ์ํ๋ ํ๋ฉด์ด ๋์ค์ง ์์๋ค. ์๊ณ ๋ณด๋, UIAlertController(.actionSheet)๋ iPad์์๋ ์์ ๊ฐ์ด, ํญํ ์์น์ ํ์
? ๋ชจ๋ฌ? ํํ๋ก ๋์ค๊ณ , iOS์์๋ ๊ธฐ์กด์ ํํ ์๊ณ ์๋ ์ก์
์ํธ ํํ๋ก ๋์จ๋ค๋๋ผ. ์ ํ์์ ์คํํ์ง๋ ์์ ๊ธฐ๋ฅ์ ์ฐ์ง ์์ ํ
๋ฐ ๋ผ๋ ์๊ฐ์ ํด์ ๊ฐ๋ฐ์ ๋ฌธ์๋ฅผ ๋ค์ ์ฐพ์๋ณด๋, UIMenu๋ผ๊ณ ๋ถ๋ฅธ๋ค๋ ๊ฒ์ ์์๋ค. ์ ..์ ๋ ์นด! var menuItems: [UIAction]..
iOS: ์คํ ๋ฆฌ๋ณด๋์์ด ์ฝ๋๋ก ๊ฐ๋ฐํ๊ธฐ
iOS: ์คํ ๋ฆฌ๋ณด๋์์ด ์ฝ๋๋ก ๊ฐ๋ฐํ๊ธฐ
2021.04.16SceneDelegate ๋ด์ฉ์ ๋ค์๊ณผ ๊ฐ์ด ๋ณ๊ฒฝ class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let scene = (scene as? UIWindowScene) else { return } window = UIWindow(windowScene: scene) window?.rootViewController = ViewController() window?.makeKeyAndVisi..
iOS: ๋ทฐ์ ๊ทธ๋ฆผ์ ๋ง๋ค๊ธฐ
iOS: ๋ทฐ์ ๊ทธ๋ฆผ์ ๋ง๋ค๊ธฐ
2021.04.16button.layer.shadowColor = UIColor.black.cgColor button.layer.shadowOffset = CGSize(width: 0.0, height: 1.0) button.layer.shadowRadius = 1.0 button.layer.shadowOpacity = 0.5 ๊ธฐ์กด ํ๋กํ
๋ฒํผ์ ์์ ๊ฐ์ด ๊ทธ๋ฆผ์๋ฅผ ์ ์ฉํ๋๋ฐ, ๋๋ฒ๊น
์ ํด๋ณด๋๊น ๋ค์๊ณผ ๊ฐ์ ๊ฒฝ๊ณ ๊ฐ ๋ด๋ค. The layer is using dynamic shadows which are expensive to render. If possible try setting 'shadowPath', or pre-rendering the shadow into an image and putting it under the..
iOS: ๋ค๋น๊ฒ์ด์
ํ์ดํ ๋ณ๊ฒฝ
iOS: ๋ค๋น๊ฒ์ด์ ํ์ดํ ๋ณ๊ฒฝ
2021.04.16let button = UIButton(type: .custom) button.setImage(UIImage(systemName: "cloud.bolt.fill"), for: .normal) button.addTarget(self, action: #selector(scrollToTop(_:)), for: .touchUpInside) self.tabBarController?.navigationItem.titleView = button ๋ฌธ์์ด ๋์ ๋ฒํผ์ด๋ ์ด๋ฏธ์ง๋ฅผ ๋ฃ๊ณ ์ถ์ผ๋ฉด ์ ์ฝ๋์ฒ๋ผ titleView์ ๋์
ํ๋ฉด ๋๋ค.(UIView ๊ฐ์ฒด) ์๋ชป ์๊ณ ์๋ ๋ด์ฉ ์ผ๋ฐ์ ์ผ๋ก ๋ค๋น๊ฒ์ด์
์ปจํธ๋กค๋ฌ๋ง ์ฌ์ฉํ๋ค๋ฉด self.navigationItem์ ํตํด ์ ๊ทผํ๋ค. ํ์ง๋ง ํญ ๋ฐ๋ฅผ ๊ฐ์ด ์ฌ์ฉํ๊ณ ์์ผ๋ฉด self...
iOS: layoutMarginsGuide, safeAreaLayoutGuide
iOS: layoutMarginsGuide, safeAreaLayoutGuide
2021.04.16iPhone 8, safeAreaLayoutGuide iPhone 8, layoutMarginsGuide iPhone 11, safeAreaLayoutGuide iPhone 11, layoutMarginsGuide layoutMarginsGuide๋ ๊ธฐ๋ณธ์ ์ผ๋ก safeAreaLayoutGuide๋ฅผ ํฌํจํ๋ฉด์ ์ถ๊ฐ๋ก ์ข์ฐ ์ฌ๋ฐฑ์ ํฌํจํ๊ณ ์๋ค.
iOS: ์ปค์คํ
์
์ ์ฉํ๊ธฐ
iOS: ์ปค์คํ ์ ์ ์ฉํ๊ธฐ
2021.04.16์คํ ๋ฆฌ๋ณด๋๋ก ์์
ํ๋ ๊ฒฝ์ฐ์๋ ๋ฑ๋กํ ํ์๊ฐ ์๋๋ฐ, ์ฝ๋๋ก ์์
ํ๋ ๊ฒฝ์ฐ์๋ ๋ฐ๋์ ๋ฑ๋กํด์ค์ผ ํ๋ค. ์ฝ๋๋ก ๋ง๋ ๊ฒฝ์ฐ collectionView.register(TweetCollectionViewCell.self, forCellWithReuseIdentifier: TweetCollectionViewCell.identifier) xib๋ก ๋ง๋ ๊ฒฝ์ฐ let nib = UINib(nibName: "TweetCollectionViewCell", bundle: nil) collectionView.register(nib, forCellWithReuseIdentifier: TweetCollectionViewCell.identifier) ๋ทฐ ์ปจํธ๋กค๋ฌ ํ๋์์ ์ฌ๋ฌ ๊ฐ์ ์
์ ๋ค๋ฃฌ๋ค๋ฉด, ์ฌ๋ฌ ๊ฐ ๋ฑ๋กํด์ค์ผ ํ๋ค. U..
iOS: ์ปฌ๋ ์
๋ทฐ ์ต์๋จ(ํน์ ์์น)์ผ๋ก ์ด๋ํ๊ธฐ
iOS: ์ปฌ๋ ์ ๋ทฐ ์ต์๋จ(ํน์ ์์น)์ผ๋ก ์ด๋ํ๊ธฐ
2021.04.16@objc func scrollToTop(_ sender: UIButton) { collectionView.scrollToItem(at: IndexPath(row: 0, section: 0), at: .top, animated: true) } ๋ค๋น๊ฒ์ด์
ํ์ดํ์ ํฐ์นํ๋ฉด ์ปฌ๋ ์
๋ทฐ ์ต์๋จ์ผ๋ก ์ด๋ํ๊ณ ์ถ์๋ค. ์ด ๋ฐ์๋ scrollToItem(at:at:animated:)์ ์ฒซ๋ฒ์งธ ์ธ์๋ก ๋ค์ด๊ฐ๋ IndexPath(row:section:)์ ์กฐ์ ํ๋ฉด ์ํ๋ ์์น๋ก ์ด๋ํ ์ ์๋ค. (์: ํน์ ์น์
์ผ๋ก ์ด๋, ํน์ ์์น๋ก ์ด๋)
iOS: UIView.clipToBounds์ layer.masksToBounds
iOS: UIView.clipToBounds์ layer.masksToBounds
2021.04.16UIView.clipToBounds ์ด ๊ฐ์ true๋ก ์ค์ ํ๋ฉด ์๋ธ ๋ทฐ๊ฐ ์์ ์์ ๊ฒฝ๊ณ์ ์๋ฆฐ๋ค. false๋ก ์ค์ ํ๋ฉด ํ๋ ์์ด ์์ ๊ธฐ์ ๊ฐ์์ ๊ฒฝ๊ณ๋ฅผ ๋์ด ํ์ฅ๋๋ ์๋ธ ๋ทฐ๋ ์๋ฆฌ์ง ์๋๋ค. ๊ธฐ๋ณธ๊ฐ์ false์ด๋ค. Setting this value to true causes subviews to be clipped to the bounds of the receiver. If set to false, subviews whose frames extend beyond the visible bounds of the receiver are not clipped. The default value is false. layer.masksToBounds ์ด ์์ฑ์ ๊ฐ์ด true์ด๋ฉด Core Animation์ ๋ ์ด..
iOS: ์ฝ๋๋ก ๋ฒํผ์ ์ด๋ฏธ์ง์ ํ
์คํธ ๋ฃ๊ธฐ
iOS: ์ฝ๋๋ก ๋ฒํผ์ ์ด๋ฏธ์ง์ ํ ์คํธ ๋ฃ๊ธฐ
2021.04.16button.setImage(UIImage(systemName: "bubble.left"), for: .normal) ์ด๋ฏธ์ง๋ฅผ ํ
์คํธ์ ์ค๋ฅธ์ชฝ์ผ๋ก ๋ณ๊ฒฝํ๋ ค๋ฉด semanticContentAttribute ์์ฑ์ .forceRightToLeft๋ก ๋ณ๊ฒฝํ๋ค. button.semanticContentAttribute = .forceLeftToRight ์ ์ฒด ์ฝ๋ let button = UIButton() button.translatesAutoresizingMaskIntoConstraints = false button.titleLabel?.adjustsFontForContentSizeCategory = true button.setImage(UIImage(systemName: "bubble.left"), for: ..