tag:blogger.com,1999:blog-81389340579628311722024-03-05T15:17:47.050-08:00iOS Code Repository (@davidbae)David Bae의 iOS 개발 이야기 (@davidbae)
재미있는 앱 개발을 위하여 개발 자료를 정리합니다. 필요한 것은 댓글로 알려주세요.Davidhttp://www.blogger.com/profile/13155437116196860250noreply@blogger.comBlogger80125tag:blogger.com,1999:blog-8138934057962831172.post-51266712854424210712020-09-05T03:51:00.002-07:002020-09-05T03:52:57.145-07:00SwiftUI의 EnvironmentValues 설명 위치<p> SwiftUI에서 EnvironmentValues에 대해서 설명하고 있는 Developer Site</p><p><a href="https://developer.apple.com/documentation/swiftui/environmentvalues">https://developer.apple.com/documentation/swiftui/environmentvalues</a></p><p>@Environment(\.verticalSizeClass) var verticalSizeClass</p><p>와 같이 환경 변수의 값을 가져올 수 있다.</p>Davidhttp://www.blogger.com/profile/13155437116196860250noreply@blogger.com0tag:blogger.com,1999:blog-8138934057962831172.post-31921776353471389552020-09-05T03:48:00.007-07:002020-09-05T03:52:26.835-07:00SwiftUI 의 속성을 이런 경우에 사용하자<p> SwiftUI Attributes Cheat Sheet: <a href="https://jaredsinclair.com/2020/05/07/swiftui-cheat-sheet.html">https://jaredsinclair.com/2020/05/07/swiftui-cheat-sheet.html</a></p><p>@State, </p><p>@Binding, </p><p>@ObservedObject, </p><p>@EnvironmentObject</p><p>@Environment</p><p>에 대해서, 어떤 경우에 사용하는 것이 맞는지 설명이 되어 있음. </p><p>참고할만함.</p>Davidhttp://www.blogger.com/profile/13155437116196860250noreply@blogger.com0tag:blogger.com,1999:blog-8138934057962831172.post-75204530612836805442020-07-10T23:26:00.001-07:002020-07-10T23:26:25.213-07:00Swift에서 로그 출력하기.<div>로그 남기는 방법을 간단히 정리해 두자</div><div><br /></div>로그 출력하는 방법에 대한 차이와 on_log 사용법<div>: <a href="https://www.it-swarm.dev/ko/swift/%EC%8A%A4%EC%9C%84%ED%94%84%ED%8A%B8-print-%EB%8C%80-println-%EA%B3%BC-nslog/1049603795/" target="_blank">스위프트 : print() 대, println () 과 NSLog()</a></div><div><br /></div><div>print()함수로 함수명과 코드 라인 등 표시하기</div><div>: <a href="https://blog.hansoolabs.com/693" target="_blank">한수댁 작업실 Blog</a></div><div><br /></div><div>Apple Developer사이트의 Logging 설명</div><div>: <a href="https://developer.apple.com/documentation/os/logging">Apple Developer Document > os > Logging</a></div><div><br /></div><div><br /></div><div>시스템 전체에서 로그 타입과 함수 위치 등을 저장하려면, </div><div>import os.log </div><div><br /></div><div>내부에서 os_log( .. ) 를 사용해서 로그를 남기고, 로그 메시지의 Level을 초기부터 적절히 나누어서 표시하도록 정의 해 두는 것이 좋겠다.</div>Davidhttp://www.blogger.com/profile/13155437116196860250noreply@blogger.com0tag:blogger.com,1999:blog-8138934057962831172.post-50574844894069613392017-05-01T00:57:00.003-07:002017-05-01T00:57:32.381-07:00iOS & Swift: Keyboard로 사용자 입력할 때, ToolBar 위로 이동하기이전 글인 <a href="http://hidavidbae.blogspot.kr/2017/03/ios-swift-keyboard.html">Keyboard 이벤트</a>를 이용해서, ToolBar를 이동하는 예제를 만들어 봅니다.<br />
<br />
ViewController에서, 하단에 Toolbar가 있고, 사용자가 입력을 할 때, View를 위로 이동시켜서, 입력하는 내용이 화면에 표시되도록 하면, 어떤 내용을 입력하는지 알기 쉬운 UI가 됩니다.<br />
<br />
ToolBar만 위로 이동해도 되지만, AutoLayout의 내용들을 다 무시하게 되므로, 전체 View를 Keyboard표시되는 것 만큼 위로 이동하게 만들어 봅니다.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTky27Wswk97S0stLi0kD4t_bxJKgUxO1NgKpb3iZZc8iS6EGO5QxFtnXbdlrsHJUUJQE-mMLnONuQqaqK_ePHfwPzeIyXGFdg580uEwfFSbnkxE7U9Kzt1ygsOW-olzTZKWm_y-Xx4H94/s1600/ToolBar%25E1%2584%258B%25E1%2585%25B1%25E1%2584%258E%25E1%2585%25B5%25E1%2584%258B%25E1%2585%25B5%25E1%2584%2583%25E1%2585%25A9%25E1%2586%25BC.gif" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTky27Wswk97S0stLi0kD4t_bxJKgUxO1NgKpb3iZZc8iS6EGO5QxFtnXbdlrsHJUUJQE-mMLnONuQqaqK_ePHfwPzeIyXGFdg580uEwfFSbnkxE7U9Kzt1ygsOW-olzTZKWm_y-Xx4H94/s320/ToolBar%25E1%2584%258B%25E1%2585%25B1%25E1%2584%258E%25E1%2585%25B5%25E1%2584%258B%25E1%2585%25B5%25E1%2584%2583%25E1%2585%25A9%25E1%2586%25BC.gif" width="171" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigeawXkyFSi2t2ssmMCHmQBsK6NLsw7CDMVTAcxO6tZNQNY71uVlDUYCFBiymO675dEW6CUYCZsOCKNwTwXLOG5iOvTdBzAxfgZQhP675GGEdNpC-Vj3ErHfxFmD4HcCS4a82T7YyZAV7L/s1600/Toolbar%25E1%2584%258B%25E1%2585%25B1%25E1%2584%258E%25E1%2585%25B5%25E1%2584%258B%25E1%2585%25B5%25E1%2584%2583%25E1%2585%25A9%25E1%2586%25BC.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><br /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigeawXkyFSi2t2ssmMCHmQBsK6NLsw7CDMVTAcxO6tZNQNY71uVlDUYCFBiymO675dEW6CUYCZsOCKNwTwXLOG5iOvTdBzAxfgZQhP675GGEdNpC-Vj3ErHfxFmD4HcCS4a82T7YyZAV7L/s1600/Toolbar%25E1%2584%258B%25E1%2585%25B1%25E1%2584%258E%25E1%2585%25B5%25E1%2584%258B%25E1%2585%25B5%25E1%2584%2583%25E1%2585%25A9%25E1%2586%25BC.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="330" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigeawXkyFSi2t2ssmMCHmQBsK6NLsw7CDMVTAcxO6tZNQNY71uVlDUYCFBiymO675dEW6CUYCZsOCKNwTwXLOG5iOvTdBzAxfgZQhP675GGEdNpC-Vj3ErHfxFmD4HcCS4a82T7YyZAV7L/s400/Toolbar%25E1%2584%258B%25E1%2585%25B1%25E1%2584%258E%25E1%2585%25B5%25E1%2584%258B%25E1%2585%25B5%25E1%2584%2583%25E1%2585%25A9%25E1%2586%25BC.png" width="400" /></a></div>
<br />
<br />
<a href="http://hidavidbae.blogspot.kr/2017/03/ios-swift-keyboard.html">Keyboard 이벤트</a> 설명 블로그에서 이벤트 등록과 이벤트 발생 때, 실행되는 함수를 등록하는 방법을 이미 설명했습니다.<br />
이제 표시될 때, ToolBar를 위로 올려주고, 입력이 끝나면 밑으로 내려줘야 합니다. 그리고, 입력 중에 화면이 회전되면, 적당하게 ToolBar의 위치를 옮겨줘야 합니다.<br />
위로 얼마나 올려야 되는지는<br />
<br />
키보드 표시될 때와, 사라질 때 함수 호출하기.<br />
<br />
<div>
<pre><code class="language-Swift"> override func viewWillAppear(_ animated: Bool) {
//화면이 표시될때, Keyboard표시에 대한 이벤트가 발생하면 호출되는 함수를 등록한다.
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillShow(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide(_:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
func keyboardWillShow(_ notification:NSNotification) {
//키보드가 표시 될때, ToolBar의 위치를 올려준다.
moveToolbarUp(with: notification)
}
func keyboardWillHide(_ notification:NSNotification) {
//키보드가 사라질 때, ToolBar의 위치를 아래로 내려준다.
moveToolbarDown(with: notification)
}
</code></pre>
</div>
<br />
Toolbar를 위로 올려주고, 아래로 내려주는 함수<br />
<div>
<pre><code class="language-Swift"> fileprivate func moveToolbarUp(with notification:NSNotification) {
self.moveToolBar(isUp: true, with: notification)
}
fileprivate func moveToolbarDown(with notification:NSNotification) {
self.moveToolBar(isUp: false, with: notification)
}
fileprivate func moveToolBar(isUp up:Bool, with notification:NSNotification) {
if let userInfo = notification.userInfo {
//let beginFrame = (userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
let endFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
let duration = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue
let animationOptions = UIViewAnimationOptions(rawValue: (userInfo[UIKeyboardAnimationCurveUserInfoKey] as! NSNumber).uintValue)
let frame = self.toolbar.frame
let rect:CGRect = CGRect(x: frame.origin.x,
y: frame.origin.y + endFrame.size.height * (up ? -1 : 1),
width: frame.size.width,
height: frame.size.height)
UIView.animate(withDuration: duration,
delay: 0.0,
options: animationOptions,
animations: { () -> Void in
self.toolbar.frame = rect
}, completion: nil)
}else{
//UserInfo가 없을 경우..
}
} </code></pre>
</div>
<br />
ToolBar가 올라가 있는 상태에서 화면을 옆으로 돌리면, 툴바의 위치가 이상하게 되어 버리는 예외를 처리하기 위해서, 화면이 회전할 때, 키보드를 사라지게 해줍니다. 더 좋은 방법이 있겠지만, 이정도로 마무리.. <br />
<br />
<div>
<pre><code class="language-Swift"> override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
//화면이 옆으로 돌아갈 때, 호출되는 이벤트로, 이벤트 발생 시, 키보드를 아래로 내려주면 이동 후에 다시 선택하면 되도록 한다
self.inputTextField.resignFirstResponder();
}
</code></pre>
</div>
<br />
<br />Davidhttp://www.blogger.com/profile/13155437116196860250noreply@blogger.com0tag:blogger.com,1999:blog-8138934057962831172.post-10048590840216308792017-03-28T07:27:00.000-07:002017-03-28T07:41:18.039-07:00iOS & Swift : Keyboard가 표시될 때, 사라질 때 이벤트와 그 키보드의 위치를 알아보자지난 블로그에서는 Objective-C를 기준으로 정리하였는데, 이제는 Swift를 기준으로 정리한다.<br />
(링크 <a href="http://hidavidbae.blogspot.com/2013/12/ios-keyboard.html">[iOS] Keyboard가 표시될 때, 사라질 때 이벤트와 그 키보드의 위치는?</a>)<br />
<br />
일반적인 UIViewController 내에서는 표시할 위치를 이동시켜야, 키보드에 덮히지 않고, 사용자에게 표시할 수 있습니다.<br />
<h3>
1. 키보드가 화면에 나타나거나, 사라지는 Event는 무엇이고, 어떻게 알아낼까?</h3>
키보드가 표시될 때 전달되는 이벤트는...<br />
<ul>
<li>NSNotification.Name.UIKeyboard<span style="color: red;">Will</span>Show : 키보드가 표시되기 전에 호출</li>
<li>NSNotification.Name.UIKeyboard<span style="color: blue;">Did</span>Show : 키보드가 표시되고 난 후에 호출</li>
<li>NSNotification.Name.UIKeyboard<span style="color: red;">Will</span>Hide : 키보드를 숨기기 전에 호출</li>
<li>NSNotification.Name.UIKeyboard<span style="color: blue;">Did</span>Hide : 키보드를 숨기고 난 후에 호출</li>
<li>NSNotification.Name.UIKeyboard<span style="color: red;">Will</span>ChangeFrame : 키보드 모양이 바뀌기 전 (iOS 5 이상)</li>
<li>NSNotification.Name.UIKeyboard<span style="color: blue;">Did</span>ChangeFrame : 키보드 모양이 바뀐 후 (iOS 5 이상)</li>
</ul>
<div>
필요한 이벤트를 viewWillAppear 함수에서 NotificationCenter에 등록합니다.</div>
<div>
Source Code</div>
<div>
<pre><code class="language-Swift"> override func viewWillAppear(_ animated: Bool) {
//화면이 표시될때, Keyboard표시에 대한 이벤트가 발생하면 호출되는 함수를 등록한다.
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillShow(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardDidShow(_:)), name: NSNotification.Name.UIKeyboardDidShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide(_:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardDidHide(_:)), name: NSNotification.Name.UIKeyboardDidHide, object: nil)
}</code></pre>
</div>
<div>
<br />
화면이 사라질 때, 등록한 것을 삭제해야 한다. 물론 삭제하면 더 이상 이벤트가 발생해도 해당 함수를 호출하지 않습니다.<br />
<br />
SourceCode</div>
<div>
<pre><code class="language-Swift"> override func viewWillDisappear(_ animated: Bool) {
//화면이 사라질 때, keyboard 표시에 대한 이벤트를 받지 않도록, 등록을 삭제한다.
NotificationCenter.default.removeObserver(self)
}
</code></pre>
<br /></div>
<div>
<br />
이벤트가 발생할 때, 호출하는 함수들을 정의한다. 해당 이름은 뭐든지 관계없으나 인자로 받는 것은 명시를 해줘야 합니다.<br />
<br />
SourceCode</div>
<div>
<pre><code class="language-Swift"> //키보드가 표시 될 때 호출 되는 함수
func keyboardWillShow(_ notification:NSNotification) {
print(notification)
info(name: "Keyboard Will beShown", with: notification)
somethingDo(with: notification)
}
func keyboardDidShow(_ notification:NSNotification) {
info(name: "Keyboard Was Shown", with: notification)
}
//키보드가 사라질 때, 호출 되는 함수
func keyboardWillHide(_ notification:NSNotification) {
info(name: "Keyboard Will beHidden", with: notification)
somethingDo(with: notification)
}
func keyboardDidHide(_ notification:NSNotification) {
info(name: "Keyboard Was Hidden", with: notification)
}</code></pre>
<br /></div>
<div>
자 이제, 키보드가 표시될 때 마다, 해당 함수들이 호출이 된다.<br />
그럼 다음으로 넘어가자.<br />
<br /></div>
<h3>
2. 호출된 키보드 이벤트 함수에서 키보드의 크기를 알아야, 다른 컴포넌트의 위치를 조정할 수 있다.</h3>
<div>
이벤트로 전달되는 NSNotification 클래스의 userInfo에서 해당 내용을 가져와야 알 수 있습니다.</div>
<div>
키보드가 표시되는 Frame의 정보는 시작할 때와 표시가 다 되었을 때, 어디에 위치할지 알아낼 수 있습니다.<br />
userInfo를 가져와서 description을 출력해 보면 아래와 같습니다.<br />
<br />
<pre><code class="language-Swift">NSConcreteNotification 0x610000242460 {name = UIKeyboardWillShowNotification; userInfo = {
UIKeyboardAnimationCurveUserInfoKey = 7;
UIKeyboardAnimationDurationUserInfoKey = "0.25";
UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {375, 258}}";
UIKeyboardCenterBeginUserInfoKey = "NSPoint: {187.5, 796}";
UIKeyboardCenterEndUserInfoKey = "NSPoint: {187.5, 538}";
UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 667}, {375, 258}}";
UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 409}, {375, 258}}";
UIKeyboardIsLocalUserInfoKey = 1;
}}
</code></pre>
<br />
위에서 표시되는 각 UserInfoKey에 대해서 조금 더 자세히 봅시다.<br />
<ul>
<li>UIKeyboardAnimationCurveUserInfoKey : 키보드가 표시될 때 Animation Curve</li>
<li>UIKeyboardAnimationDurationUserInfoKey : 키보드 표시되는 시간</li>
<li>UIKeyboardBoundsUserInfoKey : 키보드의 Bounds로 크기를 알 수 있는 bound</li>
<li>UIKeyboardCenterBeginUserInfoKey : 키보드 표시되기 시작할 때의 중심 Point</li>
<li>UIKeyboardCenterEndUserInfoKey : 키보드 표시된 후의 중심 Point</li>
<li>UIKeyboardFrameBeginUserInfoKey : 키보드가 표시되기 시작할 때의 frame</li>
<li>UIKeyboardFrameEndUserInfoKey : 키보드가 표시된 후의 Frame</li>
</ul>
<ul>
<li>UIKeyboardIsLocalUserInfoKey : 지금 표시되는 키보드가 Current App에 속한 것인지 True/False로 가지고 있음. iPad의 경우 여러 App이 화면에 표시될 수 있는데, 다른 App이 표시하는 키보드인지 내가 표시한 키보드인지 구분할 수 있음. 이것이 False이면 반응하면 안됨. (iOS 9 이상에서 지원)</li>
</ul>
아래 처럼 각 호출되는 함수에서 정보를 출력해 봅니다.<br />
<br />
SourceCode<br />
<br />
<pre><code class="language-Swift"> fileprivate func info(name str:String, with notification:NSNotification) {
if let userInfo = notification.userInfo {
let frameBegin = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue ?? CGRect.zero
let frameEnd = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue ?? CGRect.zero
let curve = userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber ?? NSNumber.init(value: 0)
let duration = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber ).doubleValue
print("\(str) (\(Int(frameBegin.origin.x)),\(Int(frameBegin.origin.y)),\(Int(frameBegin.size.width)),\(Int(frameBegin.size.height))), (\(Int(frameEnd.origin.x)),\(Int(frameEnd.origin.y)),\(Int(frameEnd.size.width)),\(Int(frameEnd.size.height))) curve:\(curve), duration:\(duration)")
}
}</code></pre>
<br />
<br />
<br />
<h3>
3. 결과로 나오는 값은 어떻게 될까요?</h3>
<br />
iPhone7<br />
세로<br />
Keyboard Will beShown (<b><span style="color: red;">0,667</span></b>,375,258), (<span style="color: blue;"><b>0,409</b></span>,375,258) curve:7, duration:0.25<br />
Keyboard Was Shown (0,667,<b><span style="color: purple;">375,258</span></b>), (0,409,375,258) curve:7, duration:0.25<br />
Keyboard Will beHidden (0,409,375,258), (0,667,375,258) curve:7, duration:0.25<br />
Keyboard Was Hidden (0,409,375,258), (0,667,375,258) curve:7, duration:0.25<br />
가로<br />
Keyboard Will beShown (<b><span style="color: red;">0,375</span></b>,667,194), (<b><span style="color: blue;">0,181</span></b>,667,194) curve:7, duration:0.25<br />
Keyboard Was Shown (0,375,<b><span style="color: purple;">667,194</span></b>), (0,181,667,194) curve:7, duration:0.25<br />
Keyboard Will beHidden (0,181,667,194), (0,375,667,194) curve:7, duration:0.25<br />
Keyboard Was Hidden (0,181,667,194), (0,375,667,194) curve:7, duration:0.25<br />
<br />
위 결과를 보시면, 표시되기 전에는 화면 아래 부분에 있다가 표시되면, 위로 올라오게 됩니다.<br />
가로/세로 모드일때 따라서, 키보드의 위치와 크기가 달라집니다.<br />
<br />
위 정보를 이용해서, UIViewController에서 ToolBar나 TextField가 키보드 아래에 있을 때, 키보드가 표시될 때 위로 이동시켜서 화면에 표시할 수 있고, 키보드가 사라질 때, 원래 위치로 이동할 수 있습니다.<br />
<br /></div>
Davidhttp://www.blogger.com/profile/13155437116196860250noreply@blogger.com5tag:blogger.com,1999:blog-8138934057962831172.post-42190150728707216842016-06-29T17:26:00.002-07:002016-07-09T17:37:29.494-07:00Swift에서 Singletons 구현하기. (Singletons in Swift)<br />
Swift에서 Class를 싱글톤으로 구현하기 위해서는 접근자를 Private로 막아서 별도로 생성하지 못하도록 해야 합니다.<br />
그리고, sharedInstance를 클래스 변수로 두어서, 이 변수를 통해서만 instance를 읽어 가도록 하면 되겠습니다.<br />
<pre><code class="language-Swift">final class SingletonObject {
static let sharedInstance = SingletonObject()
private init() {
}
}
</code></pre>
<br />
이 클래스를 읽어서 쓸 경우는 아래 같이 가져오면 되겠습니다.
<br />
<br />
<pre><code> let theInstance = SingletonObject.sharedInstance </code></pre>
<br />
<br />
<br />
원본: <a href="http://www.thomashanning.com/singletons-in-swift/">http://www.thomashanning.com/singletons-in-swift/</a><br />
<br />Davidhttp://www.blogger.com/profile/13155437116196860250noreply@blogger.com0tag:blogger.com,1999:blog-8138934057962831172.post-29167329389097722912015-02-12T08:43:00.004-08:002016-07-09T17:36:03.175-07:00[iOS] OpenSSL을 iOS용으로 컴파일하기.단계별로, 직접 컴파일 하는 방법과, build script를 이용해서 자동으로 하는 방법이 있습니다.<br />
<br />
<h3>
1. 자동으로 하는 방법</h3>
웹사이트 : <a href="https://github.com/x2on/OpenSSL-for-iPhone">https://github.com/x2on/OpenSSL-for-iPhone</a><br />
위 웹사이트에서 소스를 내려받습니다. (Download Zip)<br />
터미널에서 build-libssl.sh 를 실행하면, 자동을 만들어 줍니다.<br />
<br />
5개의 lib를 만들고, 그것을 하나로 합쳐서, universal lib로 만들어줍니다.<br />
해당 라이브러리는 /lib 밑에 libcrypto.a, libssl.a로 생성이 되고, /include에 헤더파일을 만들어 줍니다.<br />
사용하기 위해서는 lib에 있는 2개의 lib를 프로젝트에 추가하고, include를 프로젝트에서 찾을 수 있도록 추가해주면 됩니다.<br />
<br />
<h3>
2. 직접 컴파일하는 방법</h3>
<h4>
- 소스 구하기.</h4>
: 웹사이트(www.openssl.org)에서 버전을 내려 받습니다. 웹사이트에서 받거나 curl을 이용해서 받을 수 있습니다. 다운받을 버전은 1.0.1l 버전입니다.<br />
<br />
<pre><code class="language-Bash">DavidBaeui-iMac:Test DavidBae$ curl -O https://www.openssl.org/source/openssl-1.0.1l.tar.gz
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 4326k 100 4326k 0 0 279k 0 0:00:15 0:00:15 --:--:-- 820k
</code></pre>
<br />
<h4>
- 받은 파일 압출 풀기.</h4>
: Finder에서 풀거나, tar로 압축 풀기.<br />
<br />
<pre><code class="language-Bash">DavidBaeui-iMac:Test DavidBae$ mkdir src
openssl-1.0.1l.tar.gz src
DavidBaeui-iMac:Test DavidBae$ tar zxf openssl-1.0.1l.tar.gz -C /Users/DavidBae/Downloads/OpenSSL/Test/src
</code></pre>
이제 소스는 src 에 들어 있습니다.<br />
<br />
<h4>
- 소스에서 내용을 수정합니다.</h4>
<pre><code class="language-Bash">//파일이름: crypto/ui/ui_openssl.c
//413 line
//static volatile sig_atomic_t intr_signal; //sig_atomic_t를 int로 변경
static volatile int intr_signal;
</code></pre>
: 소스의 413라인 쯤에서, sig_atomic_t 를 int로 변경해야 합니다.<br />
<div class="p1">
<span class="s1"></span><br /></div>
소스가 준비가 되었으면, 총 5가지 타겟으로 컴파일을 하게 됩니다.<br />
먼저, 시뮬레이터에서 사용할 32bit(i386), 64bit(x86_64)버전,<br />
그리고, 실제 iOS에서 사용할 armv7, armv7s, arm64 버전을 각각 만듭니다.<br />
아래에서 각각 만들고 마지막에 만들어진 5개를 하나의 lib로 묶는 작업을 합니다.<br />
<br />
<br />
<h4>
- i386 타겟으로 컴파일하기.</h4>
<div>
결과를 저장할 디렉토리는 현재 디렉토리의 bin/iPhoneSimulator8.1-i386.sdk 입니다.<br />
물론 만들어놔야 겠지요.<br />
<div>
<br /></div>
./Configure 명령으로 Makefile을 만듭니다. iphoneos-cross 옵션과, 결과를 저장할 곳을 지정합니다.</div>
<pre><code class="language-Bash">DavidBaeui-iMac:openssl-1.0.1l DavidBae$./Configure iphoneos-cross --openssldir=/Users/DavidBae/Downloads/OpenSSL/Test/bin/iPhoneSimulator8.1-i386.sdk
..
..
make[1]: Nothing to be done for `links'.
generating dummy tests (if needed)...
make[1]: Nothing to be done for `generate'.
Configured for iphoneos-cross.
DavidBaeui-iMac:openssl-1.0.1l DavidBae$ //<--make파일이 다 만들어졌습니다.
</code></pre>
<div>
<br />
이제 make파일을 수정해야합니다.</div>
<div>
makefile을 열어서 아래부분을 수정합니다.<br />
<br /></div>
<pre><code class="language-Bash">CC = /Applications/Xcode.app/Contents/Developer/usr/bin/gcc -arch i386
//CFLAG= -DOPENSSL_THREADS.....
CFLAG= -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator8.1.sdk -miphoneos-version-min=7.0 -DOPENSSL....//원래 있던 옵션은 그대로 연결..
</code></pre>
<br />
makefile내부의 CFLAG에 -isysroot 옵션을 추가해 줍니다. makefile을 저장합니다.<br />
<div>
Make를 실행합니다.<br />
<br /></div>
<pre><code class="language-Bash">DavidBaeui-iMac:openssl-1.0.1l DavidBae$ make
.....
making all in tools...
make[1]: Nothing to be done for `all'.
DavidBaeui-iMac:openssl-1.0.1l DavidBae$ make install
..
..
cp openssl.pc /Users/DavidBae/Downloads/OpenSSL/Test//bin/iPhoneSimulator8.1-i386.sdk/lib/pkgconfig
chmod 644 /Users/DavidBae/Downloads/OpenSSL/Test//bin/iPhoneSimulator8.1-i386.sdk/lib/pkgconfig/openssl.pc
DavidBaeui-iMac:openssl-1.0.1l DavidBae$
//완료되었음. bin/iPhoneSimulator8.1-i386.sdk 아래에 보면 있습니다.
</code></pre>
결과는 /User/DavidBae/Download/OpenSSL/Test/bin/iPhoneSimulator8.1-i386.sdk 디렉토리에 들어 있습니다.<br />
여기에 있는 lib는 simulator의 32비트 환경에서만 동작하게 됩니다.<br />
다른 타겟으로도 컴파일하고, 이것과 같이 합쳐두어야 모든 플랫폼에서 사용할 수 있는 universal library가 됩니다.<br />
<h4>
- x86_64 타겟으로 컴파일하기.</h4>
<div class="p1">
결과를 저장할 디렉토리는 현재 디렉토리의 bin/iPhoneSimulator8.1-x86_64.sdk 입니다.<br />
물론 만들어놔야 겠지요.<br />
<br />
./Configure 명령으로 Makefile을 만듭니다. 옵션으로 darwin64-x86_64-cc가 사용되어 i386과는 다르게 설정합니다. 출력할 디렉토리도 같이 설정해 줍니다.</div>
<pre><code class="language-Bash">DavidBaeui-iMac:openssl-1.0.1l DavidBae$ ./Configure darwin64-x86_64-cc --openssldir=/Users/DavidBae/Downloads/OpenSSL/Test//bin/iPhoneSimulator8.1-x86_64.sdk
...
...
generating dummy tests (if needed)...
make[1]: Nothing to be done for `generate'.
Configured for darwin64-x86_64-cc.
DavidBaeui-iMac:openssl-1.0.1l DavidBae$
</code></pre>
<br />
makefile 변경하기.<br />
<pre><code class="language-Bash">CC = /Applications/Xcode.app/Contents/Developer/usr/bin/gcc -arch x86_64
//CFLAG= -DOPENSSL_THREADS.....
CFLAG= -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator8.1.sdk -miphoneos-version-min=7.0 -DOPENSSL....//원래 있던 옵션은 그대로 연결..
</code></pre>
<br />
makefile내부의 CC를 변경하고, CFLAG에 -isysroot 옵션을 추가해 줍니다. makefile을 저장합니다.<br />
<div>
Make를 실행합니다.<br />
<pre><code class="language-Bash">DavidBaeui-iMac:openssl-1.0.1l DavidBae$ make
.....
making all in tools...
make[1]: Nothing to be done for `all'.
DavidBaeui-iMac:openssl-1.0.1l DavidBae$ make install
..
..
cp openssl.pc /Users/DavidBae/Downloads/OpenSSL/Test//bin/iPhoneSimulator8.1-x86_64.sdk/lib/pkgconfig
chmod 644 /Users/DavidBae/Downloads/OpenSSL/Test//bin/iPhoneSimulator8.1-x86_64.sdk/lib/pkgconfig/openssl.pc
DavidBaeui-iMac:openssl-1.0.1l DavidBae$
//완료되었음. bin/iPhoneSimulator8.1-x86_64.sdk 아래에 보면 있습니다.
</code></pre>
<div>
<br /></div>
</div>
<br />
bin의 iPhoneSimulator8.1-x86_64.sdk의 lib와 include에 파일이 생성이 됨.<br />
<br />
<h4>
- armv7 타겟으로 컴파일하기.</h4>
<div class="p1">
결과를 저장할 디렉토리는 현재 디렉토리의 bin/iPhoneSimulator8.1-x86_64.sdk 입니다.<br />
물론 만들어놔야 겠지요.<br />
<br />
./Configure 명령으로 Makefile을 만듭니다. 옵션으로 darwin64-x86_64-cc가 사용되어 i386과는 다르게 설정합니다. 출력할 디렉토리도 같이 설정해 줍니다.<br />
<br /></div>
<pre><code class="language-Bash">DavidBaeui-iMac:openssl-1.0.1l DavidBae$ ./Configure iphoneos-cross --openssldir=/Users/DavidBae/Downloads/OpenSSL/Test/bin/armv7/
...
...
generating dummy tests (if needed)...
make[1]: Nothing to be done for `generate'.
Configured for iphoneos-cross.
DavidBaeui-iMac:openssl-1.0.1l DavidBae$
</code></pre>
<br />
makefile 변경하기.<br />
<pre><code class="language-Bash">CC = /Applications/Xcode.app/Contents/Developer/usr/bin/gcc -arch armv7
//CFLAG= -DOPENSSL_THREADS.....
CFLAG= -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.1.sdk -miphoneos-version-min=7.0 -DOPENSSL....//원래 있던 옵션은 그대로 연결.. CFLAG에 다른 -isysroot가 있는지 확인이 필요함.
</code></pre>
<br />
makefile내부의 CC를 변경하고, CFLAG에 -isysroot 옵션을 추가해 줍니다. makefile을 저장합니다.<br />
<div>
Make를 실행합니다.<br />
<pre><code class="language-Bash">DavidBaeui-iMac:openssl-1.0.1l DavidBae$ make
.....
making all in tools...
make[1]: Nothing to be done for `all'.
DavidBaeui-iMac:openssl-1.0.1l DavidBae$ make install
..
..
cp openssl.pc /Users/DavidBae/Downloads/OpenSSL/Test//bin/armv7/lib/pkgconfig
chmod 644 /Users/DavidBae/Downloads/OpenSSL/Test//bin/armv7/lib/pkgconfig/openssl.pc
DavidBaeui-iMac:openssl-1.0.1l DavidBae$
//완료되었음. bin/armv7 아래에 보면 있습니다.
</code></pre>
<div>
<br /></div>
<div>
bin/armv7/lib와 include에 파일이 생성이 됨.</div>
</div>
<br />
- armv7s 타겟으로 컴파일하기.<br />
: armv7을 armv7s로 변경해서, 진행<br />
<br />
- arm64 타겟으로 컴파일하기.<br />
: arm7s를 arm64로 변경해서 진행<br />
<br />
<br />
<h4>
- Universal Library 만들기</h4>
만들어진 5개의 lib를 하나로 합친다.<br />
<br />
<pre><code class="language-Bash">DavidBaeui-iMac:openssl-1.0.1l DavidBae$ lipo -create /Users/DavidBae/Downloads/OpenSSL/Test/bin/i386/lib/libssl.a /Users/DavidBae/Downloads/OpenSSL/Test/bin/x86_64/lib/libssl.a /Users/DavidBae/Downloads/OpenSSL/Test/bin/armv7/lib/libssl.a /Users/DavidBae/Downloads/OpenSSL/Test/bin/armv7s/lib/libssl.a /Users/DavidBae/Downloads/OpenSSL/Test/bin/arm64/lib/libssl.a -output /Users/DavidBae/Downloads/OpenSSL/Test/lib/libssl.
DavidBaeui-iMac:openssl-1.0.1l DavidBae$ lipo -create /Users/DavidBae/Downloads/OpenSSL/Test/bin/i386/lib/libcrypto.a /Users/DavidBae/Downloads/OpenSSL/Test/bin/x86_64/lib/libcrypto.a /Users/DavidBae/Downloads/OpenSSL/Test/bin/armv7/lib/libcrypto.a /Users/DavidBae/Downloads/OpenSSL/Test/bin/armv7s/lib/libcrypto.a /Users/DavidBae/Downloads/OpenSSL/Test/bin/arm64/lib/libcrypto.a -output /Users/DavidBae/Downloads/OpenSSL/Test/lib/libcrypto.a
DavidBaeui-iMac:openssl-1.0.1l DavidBae$
</code></pre>
<div>
OpenSSL에 대한 라이브러리가 생성이 되었다.<br />
<br />
1번에서 build-libssl.sh 을 실행하면, 2번을 했던거와 같은 방법으로, 라이브러리를 만들어 준다.<br />
<br />
잘 사용하시길....<br />
<br />
<br />
<br /></div>
Davidhttp://www.blogger.com/profile/13155437116196860250noreply@blogger.com0tag:blogger.com,1999:blog-8138934057962831172.post-53351697067848580452015-01-19T22:29:00.001-08:002015-01-19T22:29:51.723-08:00[iOS] CoreData에서 Entity의 개수를 효율적으로 읽어오기.먼저 TableViewController의 경우, NSFetchedResultController를 사용하면 가장 효율적으로 관리할 수 있습니다.<br />
특정 개수만 로딩 시켜서, 화면에 표시하므로 모든 데이터를 가져올 필요가 없게 됩니다.<br />
<br />
하지만, 특정 경우, 지금 그 Entity의 개수가 몇개인지 알아야 할 경우가 있습니다.<br />
이런때, 해당 Entity가 데이터가 크면, 그 개수 만큼의 NSManagedObject가 만들어지고, 데이터도 다 로딩 되므로, 순간 메모리 사용량이 커지게 됩니다.<br />
<br />
이 경우, NSFetchRequest의 setIncludeSubentities를 NO로 해서 subentity들이 로딩 되지 않도록 하고,<br />
context의 countForFetchRequest를 사용해서 해당되는 개수만 읽어 올 수 있게 됩니다.<br />
<br />
참조: StackOverflow: <a href="http://stackoverflow.com/questions/1134289/cocoa-core-data-efficient-way-to-count-entities" target="_blank">Cocoa Core Data efficient way to count entities!</a><br />
<br />Davidhttp://www.blogger.com/profile/13155437116196860250noreply@blogger.com0tag:blogger.com,1999:blog-8138934057962831172.post-83096431782440351002015-01-19T22:19:00.000-08:002015-01-19T22:19:17.883-08:00[iOS] unwind 함수를 코딩으로 호출하기.Storyboard에서 Exit할 수 있는 Unwind segue를 만든다.<br />
- 버튼에서 Exit로 Ctrl-Drag에서 만들 수도 있고<br />
- 해당 View Controller의 아이콘에서 Exit로 Ctrl-Drag해서 Unwind segue를 만든다.<br />
<br />
왼쪽 리스트에서 Unwind Segue from XXViewController를 선택하고, 오른쪽 Attribute Inspector에서 Identifier를 설정할 수 있다.<br />
<br />
그러면, 코드상에서 performSegueWithIdentifier로 호출할 수 있다.<br />
<br />
[참고: stackoverflow - <a href="http://stackoverflow.com/questions/12509422/how-to-perform-unwind-segue-programmatically" target="_blank">How to perform Unwind segue programmatically?</a>]<br />
<br />
<br />Davidhttp://www.blogger.com/profile/13155437116196860250noreply@blogger.com0tag:blogger.com,1999:blog-8138934057962831172.post-7401897346423260382014-12-26T00:31:00.001-08:002016-07-09T17:56:01.979-07:00[iOS] 원형의 그라디언트 이미지를 그려봅시다. (Rendering a radial gradient)<h4>
Radial Gradient</h4>
원형으로 배경을 은은하게 채워야하는 경우에, 아래와 같이 그림이 필요합니다.<br />
이미지를 만들어서 넣으면 좋겠지만, Core Graphics를 사용해서 그릴 수 있습니다.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJmxbeDb2j-9IeVsuYcUsTNRwsTwQOoSku_HhDiZcuMcVUaQildhveI4psOQF5VyJ4uJ_lkdaXhyphenhyphenj9wMOJfLe-s5u7A_9LUhuylu5YEzFgbadbXrN0xHahPKJlsgEUAh3_IDfsK-4PpF7n/s1600/iOS+Simulator+Screen+Shot+2014.+12.+26.+%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE+5.08.42.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img alt="" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJmxbeDb2j-9IeVsuYcUsTNRwsTwQOoSku_HhDiZcuMcVUaQildhveI4psOQF5VyJ4uJ_lkdaXhyphenhyphenj9wMOJfLe-s5u7A_9LUhuylu5YEzFgbadbXrN0xHahPKJlsgEUAh3_IDfsK-4PpF7n/s1600/iOS+Simulator+Screen+Shot+2014.+12.+26.+%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE+5.08.42.png" height="320" title="radial gradient" width="180"></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">만들 이미지</td></tr>
</tbody></table>
source code<br />
<pre><code class="objectivec">- (void)drawRadialGradient:(UIColor *)startColor
endColor:(UIColor *)endColor
startPoint:(CGPoint)startPoint
startRadius:(CGFloat)startRadius
endPoint:(CGPoint)endPoint
endRadius:(CGFloat)endRadius
context:(CGContextRef)context
{
CGColorRef colorRef = startColor.CGColor;
CGColorRef endColorRef = endColor.CGColor;
NSArray *marrColors=[NSArray arrayWithObjects:
(__bridge id)colorRef, //start color
(__bridge id)endColorRef, //end color
nil];
CFArrayRef colors =(__bridge CFArrayRef)(marrColors);
CGColorSpaceRef colorSpc = CGColorSpaceCreateDeviceRGB();
CGGradientRef gradient = CGGradientCreateWithColors(colorSpc, colors, Nil);
// generates Radial Gradient
CGContextDrawRadialGradient(context, gradient,
startPoint, startRadius,
endPoint, endRadius,
0);
CGColorSpaceRelease(colorSpc);
CGGradientRelease(gradient);
}
</code> </pre>
<br />
<br />
<br />
이 함수를 이용해서, 중심에 그리면, 위 만들이미지와 같은 효과를 얻을 수 있습니다.<br />
<br />
<h4>
Drawing a radial gradient like Lens</h4>
<br />
그러면, Gradient에 이미지를 추가하면 중간에 이미지가 추가가 됩니다.<br />
source code<br />
<pre><code class="objectivec">- (void)drawRadialGradient:(UIColor *)startColor
midColor:(UIColor *)midColor
endColor:(UIColor *)endColor
startPoint:(CGPoint)startPoint
startRadius:(CGFloat)startRadius
endPoint:(CGPoint)endPoint
endRadius:(CGFloat)endRadius
context:(CGContextRef)context
{
CGColorRef colorRef = startColor.CGColor;
CGColorRef midColorRef = midColor.CGColor;
CGColorRef endColorRef = endColor.CGColor;
NSArray *marrColors=[NSArray arrayWithObjects:(__bridge id)colorRef,
(__bridge id)midColorRef,
(__bridge id)endColorRef, nil];
CFArrayRef colors =(__bridge CFArrayRef)(marrColors);
CGColorSpaceRef colorSpc = CGColorSpaceCreateDeviceRGB();
CGGradientRef gradient = CGGradientCreateWithColors(colorSpc, colors, Nil);
// generates Radial Gradient
CGContextDrawRadialGradient(context, gradient,
startPoint, startRadius,
endPoint, endRadius,
0);
CGColorSpaceRelease(colorSpc);
CGGradientRelease(gradient);
}
</code></pre>
호출하는 소스
<br />
<pre><code class="objectivec">- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
// Drawing code
UIColor *whiteColor = [UIColor whiteColor];
UIColor *blueColor = [UIColor blueColor];
UIColor *greenColor = [UIColor greenColor];
CGSize size = self.frame.size;
CGPoint center = CGPointMake(size.width/2, size.height/2);
/*/
[self drawRadialGradient:greenColor endColor:self.backgroundColor
startPoint:center startRadius:0
endPoint:center endRadius:size.width/2
context:context];
/*/
[self drawRadialGradient:greenColor midColor:blueColor endColor:whiteColor
startPoint:center startRadius:0
endPoint:center endRadius:size.width/2
context:context];
CGPoint point2 = CGPointMake(size.width/2-15, size.height/2-15);
[self drawRadialGradient:whiteColor endColor:greenColor
startPoint:point2 startRadius:0
endPoint:point2 endRadius:5
context:context];
point2 = CGPointMake(size.width/2+15, size.height/2+15);
[self drawRadialGradient:whiteColor endColor:greenColor
startPoint:point2 startRadius:0
endPoint:point2 endRadius:2
context:context];
//*/
}
</code></pre>
<br />
<br />
결과물<br />
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgqasjonEHs0nIs9jrMbVMkR6OBVP0HItpntMHqmwY7ICFuU4ShZl6UIODgYZcHQnLUZyerwxZ_z1VUNCQT_L8aQKZpcmKU33NERiQfx-2WQjiKje19sZjyRvZcDYURzFd_7ldsr8GHfnm/s1600/iOS+Simulator+Screen+Shot+2014.+12.+26.+%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE+5.13.55.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgqasjonEHs0nIs9jrMbVMkR6OBVP0HItpntMHqmwY7ICFuU4ShZl6UIODgYZcHQnLUZyerwxZ_z1VUNCQT_L8aQKZpcmKU33NERiQfx-2WQjiKje19sZjyRvZcDYURzFd_7ldsr8GHfnm/s1600/iOS+Simulator+Screen+Shot+2014.+12.+26.+%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE+5.13.55.png" height="320" width="180"></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">3가지 색으로만</td></tr>
</tbody></table>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaiEnfQDc15BDDGpNFQhVhBPE0lWOsGrr76GlkEYJvyLOx2ILHNL9N_PVkkqq27FQj06oZrmcVDUNU_xWN9-TgUGq10tevxRPXsUxdeluqjFCZTQH7Cu6vrFEEBrRHxRKsW1B1cAcxycez/s1600/iOS+Simulator+Screen+Shot+2014.+12.+26.+%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE+5.14.05.png" imageanchor="1" style="clear: left; display: inline !important; margin-bottom: 1em; margin-left: auto; margin-right: auto; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaiEnfQDc15BDDGpNFQhVhBPE0lWOsGrr76GlkEYJvyLOx2ILHNL9N_PVkkqq27FQj06oZrmcVDUNU_xWN9-TgUGq10tevxRPXsUxdeluqjFCZTQH7Cu6vrFEEBrRHxRKsW1B1cAcxycez/s1600/iOS+Simulator+Screen+Shot+2014.+12.+26.+%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE+5.14.05.png" height="320" width="180"></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">3가지 색에, 점 2개 찍은것</td></tr>
</tbody></table>
<br />
<br />
나름 랜즈와 비슷한 것이 나온것 같군요.<br />
<br />
<br />
<br />
<br />
<br />
<br />Davidhttp://www.blogger.com/profile/13155437116196860250noreply@blogger.com0tag:blogger.com,1999:blog-8138934057962831172.post-53827314749166156362014-12-10T18:43:00.005-08:002016-07-09T17:58:33.907-07:00[iOS] NSString으로 된 값을 파일로 직접 저장하자.현재 App의 디렉토리 Path를 읽어 오고, 거기에 파일 이름을 추가합니다.<br />
<br />
<br />
source code<br />
<pre><code class="objectives">- (NSURL *)urlForFilename:(NSString *)filename {
NSFileManager *fm = [NSFileManager defaultManager];
NSArray *urls = [fm URLsForDirectory:NSDocumentDirectory
inDomains:NSUserDomainMask];
NSURL *directoryURL = urls[0];
NSURL *fileURL = [directoryURL URLByAppendingPathComponent:filename];
return fileURL;
}
</code></pre>
<br />
이름을 정하고 나면, NSString에서 바로 저장합니다.<br />
<br />
<br />
<pre><code class="objectives"> BOOL status = [string writeToFile:[pathUrl.path stringByAppendingPathExtension:@"txt"]
atomically:YES
encoding:NSUTF8StringEncoding
error:&error];
if (error != nil) {
NSLog(@"save error: %@", [error description]);
}
if (status == NO) {
NSLog(@"save error");
}
</code></pre>
<br />
<br />
파일로부터 데이터를 읽어 올 경우도, NSString의 카테고리를 이용합니다.<br />
<br />
<pre><code class="objectives"> NSString *string = [NSString stringWithContentsOfURL:pathUrl
encoding:NSUTF8StringEncoding
error:&error];
if (error != nil || string == nil) {
NSLog(@"Can't load file: %@, error:%@", pathUrl.path, [error description]);
}
</code></pre>
<br />
<br />
만약, 문자열이 아닌 Binary데이터를 저장하려면, NSString대신, NSData의 카테고리 함수를 이용하면, 똑같이 사용이 가능합니다.Davidhttp://www.blogger.com/profile/13155437116196860250noreply@blogger.com0tag:blogger.com,1999:blog-8138934057962831172.post-74920735627869340272014-10-09T23:04:00.001-07:002014-10-09T23:04:19.088-07:00[iOS] User Defined Runtime Attributes<h3>
User Defined Runtime Attributes란?
</h3>
Xcode의 Interface Builder에서 특정한 UI 객체에 사용자가 정의하는 값을 바로 입력하는 기능을 말합니다.<br />
Storyboard에 정의된 객체에서 값을 설정할 수 있는 것으로, Identity Inspector tab에서 설정할 수 있습니다.
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOGQO-QR7zV7uwOrcS2pNs_0BcXf4BRy464gGF8KrmvcoHwXv0iI9q3dDh_TxXPaOPOSrlIlt2_hT1bu15m22shyphenhyphenssAUIAbL1gK2WDeZx3MNZHVjohMSponm3fOcdt1awnQHf0q3nNaANe/s1600/UserDefinedRuntimeAttributes_00.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOGQO-QR7zV7uwOrcS2pNs_0BcXf4BRy464gGF8KrmvcoHwXv0iI9q3dDh_TxXPaOPOSrlIlt2_hT1bu15m22shyphenhyphenssAUIAbL1gK2WDeZx3MNZHVjohMSponm3fOcdt1awnQHf0q3nNaANe/s1600/UserDefinedRuntimeAttributes_00.png" height="446" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">InterfaceBuilder의 User Defined Runtime Attributes 설정 화면과 시뮬레이터 표시 내용.</td></tr>
</tbody></table>
<br />
위의 그림처럼 Interface Builder에서 UIView를 넣고, Identity Inspector Tab에서 값을 입력하게 되면, m파일에서 UIView의 객체를 연결해서, 직접 입력한 것처럼 동작하게 됩니다.<br />
<br />
<h4>
입력 할 수 있는 값은 어떤 것이 있을까요?</h4>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFgmEk3GCQOm5rH7YYTzsKAjbOscHXJeTfZKDO7v7kjINsVmeCf5d-Z71plM-RFhp5iCkings2CTKhxx2E6oPHVVMkJzFaQgZKCVOLs0I7sIPr63vUzPnxBPu4larYGfRGkC_ON3-Z-gUf/s1600/Attributes.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFgmEk3GCQOm5rH7YYTzsKAjbOscHXJeTfZKDO7v7kjINsVmeCf5d-Z71plM-RFhp5iCkings2CTKhxx2E6oPHVVMkJzFaQgZKCVOLs0I7sIPr63vUzPnxBPu4larYGfRGkC_ON3-Z-gUf/s1600/Attributes.png" height="277" width="320" /></a></div>
Boolean - BOOL<br />
Number - NSNumber *<br />
String - NSString *<br />
Point - CGPoint<br />
Size - CGSize<br />
Rect - CGRect<br />
Range - NSRange<br />
Color - UIColor *<br />
LocalizedString - NSString *<br />
(Localizable.string 파일에서 Key를 입력하고, 해당 locale에 맞는 string을 입력)<br />
Image - UIImage*<br />
<br />
<br />
<br />
<br />
Xcode 6에서는 총 10가지를 입력할 수 있습니다.<br />
<br />
위에 첫번째 이미지에서 layer.borderColor는 바로 설정할 수가 없습니다.<br />
전달되는 객채는 UIColor이고, layer.borderColor는 CGColorRef를 사용하기 때문입니다.<br />
가능한 방법은<br />
CALayer의 카테고리를 생성하고, 그 카테고리에 setBorderColorFromUIColor 함수를 만들어 줍니다.<br />
source code<br />
<pre class="brush:objc">#import "CALayer+extension.h"
@implementation CALayer (extension)
- (void)setBorderColorFromUIColor:(UIColor *)color
{
self.borderColor = color.CGColor;
}
@end
</pre>
<br />
h파일에도 함수를 선언해 주어야 합니다.<br />
이제, InterfaceBuilder에서 layer.borderColorFromUIColor 를 사용해서, 색상을 설정할 수 있습니다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJvUpvTJzxidDjVgIEI2gWlFe8ASxxzn4Cai-i1A1dS_ZUxkl5Jq2f7Fv9_2e3Rn7Jqjuuy8Kq355PvWnRzu3_Jn5j1Bq_WSKWWwZNtSlCeIH008XU6EpHMkPQFDRKuLWGMQ_gCA2118ni/s1600/UserDefinedRuntimeAttributes_01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJvUpvTJzxidDjVgIEI2gWlFe8ASxxzn4Cai-i1A1dS_ZUxkl5Jq2f7Fv9_2e3Rn7Jqjuuy8Kq355PvWnRzu3_Jn5j1Bq_WSKWWwZNtSlCeIH008XU6EpHMkPQFDRKuLWGMQ_gCA2118ni/s1600/UserDefinedRuntimeAttributes_01.png" height="410" width="640" /></a></div>
<br />
위의 시뮬레이터에서 테두리 색상이 설정된 것을 볼 수 있습니다.<br />
<br />
<br />
<h4>
[참고]</h4>
- iOS-Blog : <a href="http://ios-blog.co.uk/tutorials/user-defined-runtime-attributes/">User Defined Runtime Attributes</a>
<br />
- ATOMIC SPIN : <a href="http://spin.atomicobject.com/2014/05/30/xcode-runtime-attributes/">Expanding User-Defined Runtime Attributes in Xcode with Objective-C</a><br />
<br />
<br />
<br />
<br />Davidhttp://www.blogger.com/profile/13155437116196860250noreply@blogger.com0tag:blogger.com,1999:blog-8138934057962831172.post-9667121503853603662014-09-12T01:05:00.001-07:002014-09-12T01:06:45.963-07:00[iOS] 물방울 모양의 UIView를 만들자.UIView의 모양을 물방울 모양으로 변형을 해보겠습니다.<br />
<br />
1. UIBezierPath를 이용해서, 물방울 모양의 Path를 만듭니다.<br />
<br />
source code<br />
<pre class="brush:objc">- (UIBezierPath *)waterDropPath:(CGRect)frame
{
//NSLog(@"makeWaterDropPathIn: %@", NSStringFromCGRect(frame) );
float x = frame.origin.x;
float y = frame.origin.y;
float hW = frame.size.width/2.0f;
float H = frame.size.height;
CGPoint sp = CGPointMake(x+hW, y); //Start point
CGPoint cp = CGPointMake(x+hW, y+H-hW); //Center point
CGPoint b1 = CGPointMake(x, y+H-hW); //WaterDrop left point
CGPoint c1 = CGPointMake(x+hW, y+hW+hW/2); //왼쪽 내려오는 부분에서 사용
CGPoint c2 = CGPointMake(x, y+H-hW-hW);
CGPoint c3 = CGPointMake(x+hW+hW, y+H-hW-hW); //오른쪽 올라가는 부분에서 사용
UIBezierPath *path = [[UIBezierPath alloc] init];
[path setLineWidth:0.5f];
[path moveToPoint:sp]; //시작점으로 이동
[path addCurveToPoint:b1
controlPoint1:c1
controlPoint2:c2]; //왼쪽 물방울 내려오는 부분
[path addArcWithCenter:cp
radius:hW//-0.5f
startAngle:DEGREE_TO_RADIAN(180)
endAngle:DEGREE_TO_RADIAN(0)
clockwise:NO]; //물방울 아래부분
[path addCurveToPoint:sp
controlPoint1:c3
controlPoint2:c1]; //오른쪽 올라가는 부분
return path;
}
</pre>
<br />
2. Path로 부터 현재 뷰의 layer의 mask를 설정합니다.<br />
<br />
source code <br />
<pre class="brush:objc">- (void) setWaterDropClippingArea:(CGRect)frame
{
//클립핑 영역을 만든다.
[self setClippingAreaFromPath:[self waterDropPath:frame]];
}
- (void)setClippingAreaFromPath:(UIBezierPath *)path
{
CAShapeLayer *mask = [CAShapeLayer layer];
mask.path = path.CGPath;
self.layer.mask = mask;
}
</pre>
<br />
3. 결과물<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQTVaeUqRr7neCqMjTIsZlI98f0AfEvc8qBaVZdQrqiQ-d3g4NQJDEn6tDAYij7Q2P-3luHLIA3G5fk-k3r5o83bXmmZXzFJv9QMTCjZTuQIxiguIthpUEKEekBnS75UZBrazL3iYcNfkE/s1600/iOS+Simulator+Screen+shot+2014.+9.+12.+%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE+4.51.59.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQTVaeUqRr7neCqMjTIsZlI98f0AfEvc8qBaVZdQrqiQ-d3g4NQJDEn6tDAYij7Q2P-3luHLIA3G5fk-k3r5o83bXmmZXzFJv9QMTCjZTuQIxiguIthpUEKEekBnS75UZBrazL3iYcNfkE/s1600/iOS+Simulator+Screen+shot+2014.+9.+12.+%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE+4.51.59.png" height="400" width="225" /></a></div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfULuE1GfCBanu_d1KYfuxHdF6kNPRPQAf7kDVAFvi7dXWHGc2RJaKcKYo-T_UEyQsAjliiaZyZ6Zjr4yE3AtSV7_AVMlyFINcMgi2xsMIjk0CHkcM7D_6BZdIVaGHjpQo5uOdqWh6dD6L/s1600/iOS_Simulator_Screen_shot_2014__9__12__%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_4_51_59.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfULuE1GfCBanu_d1KYfuxHdF6kNPRPQAf7kDVAFvi7dXWHGc2RJaKcKYo-T_UEyQsAjliiaZyZ6Zjr4yE3AtSV7_AVMlyFINcMgi2xsMIjk0CHkcM7D_6BZdIVaGHjpQo5uOdqWh6dD6L/s1600/iOS_Simulator_Screen_shot_2014__9__12__%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_4_51_59.png" height="400" width="225" /></a><br />
<br />
위 소스의 sp, cp, b1, c1, c2, c3 위치를 왼쪽에 표시하였습니다.<br />
<br />
<br />
<br />
<br />Davidhttp://www.blogger.com/profile/13155437116196860250noreply@blogger.com0tag:blogger.com,1999:blog-8138934057962831172.post-90719953633996107642014-07-13T05:00:00.003-07:002014-07-13T05:02:29.189-07:00[iOS] 크기에 맞게 Font의 크기 줄이기.Storyboard에서 문자열을 표시를 해야 되는데...<br />
단어나, 길지 않은 문자열은 크기를 200포인트로 표시하고, 만약 길이가 길다면, 그보다 작은 크기로 크기가 맞을 때까지 폰트의 크기를 줄이는 기능이 필요합니다.<br />
<br />
<br />
<pre class="brush:objc">
//1
+ (UIFont *) spq_getFontForLabel:(NSString *)string font:(UIFont *)font size:(CGSize)size
{
BOOL isEnough = NO;
UIFont *afont = font; //2
while (!isEnough) {
//3
CGRect aboutRect = [string //높이를 구할 NSString
boundingRectWithSize:CGSizeMake(size.width*0.9, CGFLOAT_MAX)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:@{NSFontAttributeName:font}
context:nil];
//4
if (aboutRect.size.height > (size.height*0.7)) {
//5
font = [UIFont fontWithName:font.fontName size:font.pointSize*0.9];
}else{
isEnough = YES;
afont = font;
}
}
return afont;
}
</pre>
<br />
위 소스에서<br />
1: 대상이 되는 문자열과, 그 문자열에 적용되어 있는 Font, 그리고 어떤 너비에서 계산을 해야 되는지 파라미터로 넘겨 줍니다.<br />
2 : while문을 통해서, 크기가 작어질 때까지 적용 합니다.<br />
3 : NSString의 boundingRectWithSize를 이용해서, 대략적인 rect를 구합니다.<br />
여기에서, 너비의 90%정도를 고려해서 넣습니다. 100% 크기를 하면 옆으로 너무 딱 붙어서 계산이 되어서, 90%크기로 적용해 줍니다.<br />
4 : 계산된 크기가, 대상 높이의 70%보다 크면, 줄여 줍니다. 70%는 대략적으로 생각한 것으로 높의 70%이하가 되는 것이 적당하였습니다. (적용할 때, 변경해서 보시면 됩니다.)<br />
5 : 아직 커서 줄여야 되면, 현재 font 의 name과 크기의 90%를 적용해서 폰트를 다시 만들고 적용해 줍니다.<br />
이 폰트를 가지고 while문 안에서 다시 계산을 하게 됩니다.<br />
<br />
감사합니다.Davidhttp://www.blogger.com/profile/13155437116196860250noreply@blogger.com0tag:blogger.com,1999:blog-8138934057962831172.post-75050588266162828902014-07-12T20:36:00.001-07:002014-07-12T20:36:52.934-07:00[iOS] 문자열에 대해서, 언어 알아내기.문자열에서 언어에 따라서 다른 폰트를 설정해야 하는 경우가 있습니다.<br />
이럴 경우, NSString에서 언어를 알아내서, 적절하게 구분할 수 있습니다.<br />
<br />
<pre class="brush:objc">- (NSString *)languageForString:(NSString *) text{
return (NSString *)CFBridgingRelease(CFStringTokenizerCopyBestStringLanguage((CFStringRef)text, CFRangeMake(0, MIN(text.length, 100))));
}
</pre>
<br />
참고:
<a href="http://stackoverflow.com/questions/14231023/how-to-deal-with-the-ios-detect-the-nsstring-language-english-can-not-be-detect">How to deal with the iOS detect the NSString language, English can not be detected accurately?</a>Davidhttp://www.blogger.com/profile/13155437116196860250noreply@blogger.com0tag:blogger.com,1999:blog-8138934057962831172.post-44561458680981131252014-07-12T19:56:00.003-07:002014-07-12T19:56:51.712-07:00[iOS] 무료사운드 구해서, AVAudioPlayer로 Play하기<h4>
사운드 찾기</h4>
무료 사운드를 받을 수 있는 곳은 찾아보면 많습니다.<br />
<br />
<ul>
<li>freeSFX : <a href="http://www.freesfx.co.uk/">http://www.freesfx.co.uk/</a></li>
</ul>
<div>
필요한 mp3파일을 찾아서 다운받습니다.</div>
<div>
<br /></div>
<div>
<h4>
사운드 변경하기</h4>
</div>
<div>
보통 MP3파일을 받게 되는데, 이것을 CAF파일로 변경합니다.</div>
<div>
터미널에서 파일(bass_ring.mp3)를 caf로 변경합니다.</div>
<div>
<br /></div>
<div class="p1">
afconvert -f caff -d LEI16@22050 brass_ring.mp3 brass_ring.caf</div>
<div class="p1">
<br />
<div>
<h4>
iOS에서 play하기</h4>
</div>
<div>
AVAudioPlayer를 생성하고, 필요한 시점에 play/stop을 실행합니다.<br />
<br /></div>
<pre class="brush:objc">//선언
AVAudioPlayer *_backgroundMusic;
//viewDidLoad에서 준비
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
NSURL *url = [[NSBundle mainBundle] URLForResource:@"brass_ring" withExtension:@"caf"];
_backgroundMusic = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
[_backgroundMusic prepareToPlay];
}
//viewWillAppear에서 실행
- (void)viewWillAppear:(BOOL)animated{
[_backgroundMusic play];
}
//viewWillDisappear에서 중지
- (void)viewWillDisappear:(BOOL)animated
{
[_backgroundMusic stop];
}
</pre>
</div>
Davidhttp://www.blogger.com/profile/13155437116196860250noreply@blogger.com0tag:blogger.com,1999:blog-8138934057962831172.post-10768447530595863022014-07-11T23:32:00.003-07:002014-07-11T23:32:24.135-07:00[iOS] CoreData관련한 몇가지 정리할 내용들..개발하면서, CoreData를 사용할 때 필요한 내용을 정리합니다.<br />
<h4>
RAW SQL</h4>
CoreData관련 코드를 작성하고 테스트하다 보면, 실제 SQL이 어떻게 동작되는지 궁금할 때가 있습니다.<br />
어떤 SQL문이 언제 호출이 되어서 실행이 되는지 보면, Commit을 언제 해야 될지 적절할 시기를 알 수 있습니다.<br />
XCode의 Scheme을 드롭다운해서 열고, Edit Scheme을 선택, 'Run {app name}'을 선택하고, Arguments 탭에서 Arguments Passed On Launch에 '+'버튼을 선택해서 아래 내용을 추가합니다.<br />
'<span style="background-color: white; font-family: 'Open Sans', sans-serif; font-size: 16px; line-height: 25.8799991607666px;"><b>-com.apple.CoreData.SQLDebug 1</b>'</span><br />
<span style="background-color: white; font-family: 'Open Sans', sans-serif; font-size: 16px; line-height: 25.8799991607666px;">그리고 실행을 하면, 실제 SQL문이 어떻게 호출 되는지 표시가 됩니다.</span><br />
<span style="background-color: white; font-family: 'Open Sans', sans-serif; font-size: 16px; line-height: 25.8799991607666px;"><br /></span>
<br />
<h4>
<span style="font-family: Open Sans, sans-serif;"><span style="background-color: white; line-height: 25.8799991607666px;">CoreData에서 Object가져오기.</span></span></h4>
<span style="font-family: Open Sans, sans-serif;"><span style="background-color: white; line-height: 25.8799991607666px;">AppDelegate에 추가한 함수를 통해서 managedContext를 받아와야 읽거나, 저장할 수 있습니다.</span></span><br />
<span style="font-family: Open Sans, sans-serif;"><span style="background-color: white; line-height: 25.8799991607666px;">CoreData에서 데이터를 fetch해서 가져오기 위해서, NSFetchRequest를 만들고, executeFetchRequest를 통해서, NSManagedObject의 형태로 받아 옵니다.</span></span><br />
<span style="font-family: Open Sans, sans-serif;"><span style="background-color: white; line-height: 25.8799991607666px;">받아올 때, 필터링하기 위해서, NSPredicate를 설정하고, 정렬해서 보기 위해서 NSSortDescriptor를 설정합니다.</span></span>
<span style="font-family: Open Sans, sans-serif;"><span style="background-color: white; line-height: 25.8799991607666px;"><br /></span></span>
<br />
<pre class="brush:objc">- (void) function
{
NSError *error;
SPQAppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
NSManagedObjectContext *managedContext = [appDelegate managedObjectContext];
NSFetchRequest *request;
request = [NSFetchRequest fetchRequestWithEntityName:entityName];
request.predicate = [NSPredicate predicateWithFormat:@"name = %@ && created=%@", name, (created)?@"YES":@"NO"];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];
request.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *items = [managedContext executeFetchRequest:request error:&error];
if (error != nil) {
NSLog(@"executeFetchRequest: %@", [error localizedDescription]);
}
//....
}
</pre>
<pre class="brush:objc"></pre>
<br />
<h4>
새로운 Object 만들기</h4>
신규로 object를 만들고, 거기에 값을 넣은 후, 저장을 하면, CoreData에 저장이된다.<br />
<pre class="brush:objc"> item = [NSEntityDescription insertNewObjectForEntityForName:entityName //추가할 entity이름
inManagedObjectContext:managedContext];
</pre>
<br />
<br />
<h4>
기존 Object 지우기.</h4>
managedObject를 찾은 다음, 그 object를 manageObjectContext에서 삭제하면 된다.<br />
<pre class="brush:objc"> [managedContext deleteObject:item]; //item은 NSManageObject 임.
</pre>
<br />
<h4>
Boolean값을 비교하기</h4>
predicate를 만들 때, String은 '=='로 비교를 하지만, Bool인 경우에는 NSNumber를 이용해서 비교를 해야 한다.<br />
<pre class="brush:objc"> [NSPredicate predicateWithFormat:@"name == %@, created == %@", name, [NSNumber numberWithBool:created]];
</pre>
<br />
제가 필요한 것만 정리를 해 둡니다.<br />
<br />Davidhttp://www.blogger.com/profile/13155437116196860250noreply@blogger.com0tag:blogger.com,1999:blog-8138934057962831172.post-68738409998098150462014-05-22T23:06:00.000-07:002014-05-23T16:17:22.226-07:00[iOS] Poster Scroll View를 만들어 봅니다.영화관 앱에서 포스터를 옆으로 넘길 때, 현재 페이지의 이미지와, 다음페이지의 이미지가 약간 겹처서 넘어갑니다.<br />
Yahoo 날씨 앱에서도 각 페이지를 양 옆으로 넘길 때, 이미지가 겹쳐서 넘어가게 됩니다.<br />
<br />
이것을 스크롤 뷰를 이용해서 구현해 보도록 하겠습니다.<br />
<br />
<h4>
1. 전체 구현방법</h4>
스크롤 뷰에 현재 frame크기의 각 페이지로 커스텀 뷰(DBUMoviePosterView)를 추가하고, 화면이 이동할 때, 커스텀 뷰에서 이미지의 위치를 조정해주게 된다.<br />
이 커스텀 뷰에서 추가된 내부 뷰가 이동할 때, 배경이 바깥 부분으로 나가지 않도록 레이어의 masksToBound도 설정해 준다.<br />
오른쪽에서 왼쪽으로 다음페이지의 이미지가 나올 때는, 현재 위치를 계산해서, 중간에서 오른쪽으로 이동하도록 하고,<br />
왼쪽에서 오른쪽으로 이전 페이지의 이미지가 나올 때, 중간에서 왼쪽으로 이동하도록 한다.<br />
<br />
<h4>
2. 소스 구현</h4>
- DBUScrollView<br />
source code<br />
<pre class="brush:objc">@interface DBUScollView()
@property (nonatomic, strong) NSMutableArray *posters;
@end
@implementation DBUScollView
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
self.delegate = self;
}
return self;
}
- (NSMutableArray *)posters
{
if (_posters == nil) {
_posters = [NSMutableArray array];
}
return _posters;
}
- (void)addPoster:(UIImage *)image
{
CGSize size = self.frame.size;
//포스터 전체 개수
NSUInteger posterTotalCount = [self.posters count];
//content 영역 설정
self.contentSize = CGSizeMake(size.width * (posterTotalCount+1), size.height);
// 포스터 뷰 생성 및 추가
DBUMoviePosterView *posterView = [[DBUMoviePosterView alloc] initWithFrame:CGRectMake(size.width*(posterTotalCount), 0, size.width, size.height)];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:posterView.bounds];
imageView.image = image;
[posterView addView:imageView];
[self addSubview:posterView];
//위치 이동을 위해서, Array로 보관
[self.posters addObject:posterView];
}
#pragma mark - UIScrollViewDelegate
- (void)posterImagePosition:(NSInteger)posterIndex point:(CGPoint)point
{
if (posterIndex < 0 || posterIndex >= self.posters.count) {
return; //페이지 수를 벗어난 것이면, 무시한다.
}
DBUMoviePosterView *posterView = (DBUMoviePosterView *)self.posters[posterIndex];
if (posterView == nil) return;
[posterView moveViewPosition:point]; //각 포스터 뷰에서 내부 뷰를 이동시킨다.
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
//현재 페이지를 계산해서, 연재와 다음 것만 움직이도록 한다.
NSUInteger currentPage = scrollView.contentOffset.x / scrollView.frame.size.width;
//계산은 각 포스터 뷰에서 계산한다.
[self posterImagePosition:currentPage point:scrollView.contentOffset];
[self posterImagePosition:currentPage+1 point:scrollView.contentOffset];
}
@end
</pre>
<br />
<br />
<br />
- DBUMoviePosterView<br />
source code<br />
<pre class="brush:objc">#import "DBUMoviePosterView.h"
@interface DBUMoviePosterView()
{
UIView *_view;
}
@end
@implementation DBUMoviePosterView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
self.layer.masksToBounds = YES;//
}
return self;
}
- (void) addView:(UIView *)view
{
if (_view != nil) {
[_view removeFromSuperview];
_view = nil;
}
_view = view;
[self addSubview:view];
}
- (void) moveViewPosition:(CGPoint)point
{
CGFloat width = self.frame.size.width;
CGFloat height = self.frame.size.height;
CGFloat x = point.x - self.frame.origin.x;
if (x > -width && x < width) {
//현재 위치와 비교한 값의 절반을 x좌표로 한다.
_view.frame = CGRectMake(x/2, point.y, width, height);
}
}
- (void) moveViewPositionToInitial
{
//(0,0)으로 원위치 시킴.
[self moveViewPosition:CGPointMake(0, 0)];
}
</pre>
<br />
<br />
<h4>
3. 결과물</h4>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhX79qOXD6devEHS7Ao1eNcVvlCnQJwNOmc0epg0HmqALSN9CTkNLWRss-tAVgoDOgblDLNXQoVSdGBm5Q_PxAh3EmctukqvHRJ8JjRgaQApywI9eDRKb1XG1LDu1SC890uQhDThubiKvP9/s1600/2014-05-23+15_00_43.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhX79qOXD6devEHS7Ao1eNcVvlCnQJwNOmc0epg0HmqALSN9CTkNLWRss-tAVgoDOgblDLNXQoVSdGBm5Q_PxAh3EmctukqvHRJ8JjRgaQApywI9eDRKb1XG1LDu1SC890uQhDThubiKvP9/s1600/2014-05-23+15_00_43.gif" height="640" width="362" /></a></div>
<br />
<br />
<br />Davidhttp://www.blogger.com/profile/13155437116196860250noreply@blogger.com0tag:blogger.com,1999:blog-8138934057962831172.post-1905261454049031592014-05-22T00:52:00.001-07:002014-05-22T00:55:33.171-07:00[iOS] sizeWithFont를 대체하는 함수 사용법iOS7이전에는 NSString이 특정 가로 크기에서 줄바꿈 등을 통해서, 높이가 얼마나 되는지 알아보기 위해서는 sizeWithFont:constrainedToSize를 사용하였는데, 7.0에서는 Deprecated가 되어서 변경해야 합니다.<br />
iOS7에서는 font뿐만 아니라, 다른 Attribute들도 높이를 구할 때 필요하므로 font만 참고하는 것이 아니라, attributes라고 NSDictionary를 받아서 구하게 됩니다.<br />
<br />
sizeWithFont:constrainedToSize (Deprecated)<br />
<pre class="brush:objc"> //특정 영역 (268, 4000)의 크기에서 myString에 있는 글의 높이를 iOS6에서 구하는 방법
UIFont *font = [UIFont fontWithName:@"HelveticaNeue-Light" size:10];
CGSize aboutSize = [myString sizeWithFont:font constrainedToSize:CGSizeMake(268, 4000)];
</pre>
<br />
<br />
Xcode5에서는 boundingRectWithSize:options:attributes:context:를 사용하라고 나옵니다.
<br />
<br />
<pre class="brush:objc"> //폰트가 따로 정리가 되어 있지 않는 경우는
UIFont *font = [UIFont fontWithName:@"HelveticaNeue-Light" size:10];
CGRect aboutRect = [myString //높이를 구할 NSString
boundingRectWithSize:CGSizeMake(268, CGFLOAT_MAX)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:@{NSFontAttributeName:font}
context:nil];
</pre>
<br />
만약 일반 NSString이 아니고, NSAttributedString을 사용하고 있으면, attributes가 없는 함수를 사용하면 됩니다.<br />
<br />
<pre class="brush:objc"> //폰트가 따로 정리가 되어 있지 않는 경우는
UIFont *font = [UIFont fontWithName:@"HelveticaNeue-Light" size:10];
NSAttributedString *myAttributedString = [[NSAttributedString alloc] initWithString:myString
CGRect aboutRect = [myAttributedString //높이를 구할 NSAttributedString
boundingRectWithSize:CGSizeMake(268, CGFLOAT_MAX)
options:NSStringDrawingUsesLineFragmentOrigin
context:nil];
</pre>
<br />
정리해 둡니다.Davidhttp://www.blogger.com/profile/13155437116196860250noreply@blogger.com0tag:blogger.com,1999:blog-8138934057962831172.post-17251664844277711142014-05-17T01:31:00.002-07:002014-05-17T01:31:22.784-07:00[iOS] Facebook에 글과 이미지, 링크 등록하기.iOS6 부터 Facebook에 글을 올릴 수 있는 방법을 제공하고 있습니다.<br />
내부 동작방식은 Twitter에 올리는 것과 동일한 방법에 서비스 타입만 변경하면 됩니다.<br />
<br />
<a href="http://hidavidbae.blogspot.com/2014/05/ios6-twitter.html">Twitter에 글 올리기 </a><br />
<br />
위의 트위터에 글 올리기에 설명한 것과 같이, 이미지와 URL을 추가할 수 있습니다.<br />
<br />
source code<br />
<pre class="brush:objc">- (IBAction)uploadToFacebook:(UIBarButtonItem *)sender {
if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeFacebook]) {
SLComposeViewController *composer = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook];
[composer setInitialText:@"Initial Text for Facebook :)"];//초기 메시지.
[composer addImage:self.uploadImage]; //추가할 이미지
[composer addURL:[NSURL URLWithString:APP_URL_IN_ITUNES]];//추가할 URL
composer.completionHandler = ^(SLComposeViewControllerResult result){
switch(result) {
// This means the user cancelled without sending the Tweet
case SLComposeViewControllerResultCancelled:
break;
// This means the user hit 'Send'
case SLComposeViewControllerResultDone:
break;
}
};
[self presentViewController:composer animated:YES completion:^{
//NSLog(@"present completed");
}];
}else{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Sorry"
message:@"You can't upload this page to Facebook right now, make sure your device has an internet connection and you have at least one Facebook account setup"
delegate:self cancelButtonTitle:@"OK"
otherButtonTitles: nil];
[alertView show];
}
}
</pre>
<br />
페이스북에 대한 연결이 되어 있지 않은 경우, 아래와 비슷하게 업로드를 할 수 없다고 알려줘야 합니다.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhulzcmirWNd-QZjqbVNAg637GHL8PfMJBR6bKTLheXWHYa5YqkcZuoPbX2I3r4lI9i5TWEYgKopM00IHUosOpCye_JqSt9vjsAb6VO_Y9lcPh6lv9UZpw8kPYhIduQaBJT6-Vh-2XiD1Fm/s1600/Facebook+00.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhulzcmirWNd-QZjqbVNAg637GHL8PfMJBR6bKTLheXWHYa5YqkcZuoPbX2I3r4lI9i5TWEYgKopM00IHUosOpCye_JqSt9vjsAb6VO_Y9lcPh6lv9UZpw8kPYhIduQaBJT6-Vh-2XiD1Fm/s1600/Facebook+00.png" height="400" width="225" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Upload가 불가능함을 알림.</td></tr>
</tbody></table>
만약, 아이디가 설정이 되어 있으면, 아래와 같이 Facebook Composer가 표시가 됩니다.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKK1GLk3lhgwnU9pIoJgbuGPREs1pKMt_PK3SoFr7iApCiKfBehTbn0st4nEc7JlJy3oyrsa4MISzMEwGQJZe0LEANUHhVG2kvJpP8o7X3Bt0M7gQgF7ZDb__pnCqC8D0pjg7pybVI1tYp/s1600/Facebook+01.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKK1GLk3lhgwnU9pIoJgbuGPREs1pKMt_PK3SoFr7iApCiKfBehTbn0st4nEc7JlJy3oyrsa4MISzMEwGQJZe0LEANUHhVG2kvJpP8o7X3Bt0M7gQgF7ZDb__pnCqC8D0pjg7pybVI1tYp/s1600/Facebook+01.png" height="400" width="225" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">페이스북 타입의 SLComposeViewController</td></tr>
</tbody></table>
이미지를 어느 앨범에 올릴지, 현재 위치를 추가할지, 공개를 어느 범위까지 할지 표시합니다.<br />
만약, 이 화면에서 Post를 했는데, 인터넷 연결이 안되어 있는 경우, 아래와 같이 표시가 됩니다.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-sUQ41kA7OicFjWfsSbkIhoOS1kOxP-jEmaFhAKs1LkWOWsMOqOykMfyF9lLqQd7fUEBroLMCbGDC1FVwfM51Vl8szQOiK-yQyQd4d4KF8omKkEz2zCEugMsNzCqUQw18FxL4HlnL3cVV/s1600/Facebook+02.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-sUQ41kA7OicFjWfsSbkIhoOS1kOxP-jEmaFhAKs1LkWOWsMOqOykMfyF9lLqQd7fUEBroLMCbGDC1FVwfM51Vl8szQOiK-yQyQd4d4KF8omKkEz2zCEugMsNzCqUQw18FxL4HlnL3cVV/s1600/Facebook+02.png" height="400" width="225" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Facebook에 Upload하지 못할 경우 표시화면</td></tr>
</tbody></table>
<br />
<br />
<br />
참고:<br />
- <a href="http://www.techotopia.com/index.php/Integrating_Twitter_and_Facebook_into_iOS_7_Applications">Integrating Twitter and Facebook into iOS7 Applications</a><br />
- <a href="http://soulwithmobiletechnology.blogspot.kr/2012/07/tutorial-how-to-use-inbuilt.html">Mobile and Social Network Technology - Tutorial: How to use inbuilt Facebook/Twitter API in iOS6</a><br />
- <a href="http://www.appcoda.com/tag/slcomposeviewcontroller/">iOS Programming 101: Integrate Twitter and Facebook Sharing in Your App.</a><br />
- <a href="http://maniacdev.com/2012/10/open-source-control-for-creating-slcomposeviewcontroller-type-views-for-any-social-network">Open Source Control For Creating SLComposeViewController Type Views For Any Social Network</a><br />
<br />
<br />
<br />Davidhttp://www.blogger.com/profile/13155437116196860250noreply@blogger.com0tag:blogger.com,1999:blog-8138934057962831172.post-1237922055596964852014-05-15T23:02:00.000-07:002014-05-15T23:02:07.024-07:00[iOS6] Twitter에 이미지와 링크 올리기iOS6에서 트위터에 이미지와 글을 올릴 수 있는 방법을 자체 Framework으로 제공하고 있습니다.<br />
Social.framework를 추가하고, social/social.h 를 임포트한 후에 실행 시킬 수 있습니다.<br />
<br />
1. 트윗을 보낼 수 있는지 확인하는 코드<br />
SLComposerViewController의 isAvailableForServiceType 함수를 통해서 확인할 수 있으며, 전송하지 못할 경우, 사용자에게 적절한 문구를 보여줘야 합니다.<br />
<br />
2. 전송한 결과값을 받아야 하는 경우<br />
completionHandler에 블록 함수를 설정해서, 결과를 받아올 수 있습니다.<br />
<br />
3. 초기 메시지 추가<br />
- setInitialText를 통해서 초기 메시지를 넣을 수 있습니다.<br />
<br />
4. 이미지 추가<br />
- addImage : 이미지를 추가할 수 있습니다.<br />
<br />
5. URL 추가<br />
- addURL: NSURL객체를 추가할 수 있습니다.<br />
<br />
source code<br />
<pre class="brush:objc">#import <social ocial.h="">
@import Social;
...
- (IBAction)tweetThisPage:(UIBarButtonItem *)sender
{
if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeTwitter]) {
SLComposeViewController *composer = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeTwitter];
[composer setInitialText:@"This is my first tweet in my app!"];
[composer addImage:[self loadImage]];
[composer addURL:[NSURL URLWithString:APP_URL_IN_ITUNES]];
composer.completionHandler = ^(SLComposeViewControllerResult result){
switch(result) {
// This means the user cancelled without sending the Tweet
case SLComposeViewControllerResultCancelled:
NSLog(@"Canceled");
break;
// This means the user hit 'Send'
case SLComposeViewControllerResultDone:
NSLog(@"Tweet Done");
break;
}
};
[self presentViewController:composer animated:YES completion:^{
NSLog(@"Tweet Composer present completed");
}];
}else{</social></pre>
<pre class="brush:objc"><social ocial.h=""> //트위터 아이디가 설정되어 있지 않거나, 인터넷에 연결이 안되어 있는 경우..
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Sorry"
message:@"You can't send a tweet right now, make sure your device has an internet connection and you have at least one Twitter account setup"
delegate:self cancelButtonTitle:@"OK"
otherButtonTitles: nil];
[alertView show];
}
}
</social></pre>
<br />
설정에 트위터 아이디가 설정이 되어 있지 않으면, 아래와 같이 표시가 됩니다.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCU48exs7QeNRHvuVeUcAwI_3nX9EYnea5HtABQ6uyOw9aBOy1-rlMWboVxMk6JtSnSQX9HMYvioRRkzvb46sQOJDn3Iu322IzBaaV18IKLx8FBR-QZ4RhjV4rYzqYu2K7J7ZVcVUoi0rx/s1600/00+Tweet.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCU48exs7QeNRHvuVeUcAwI_3nX9EYnea5HtABQ6uyOw9aBOy1-rlMWboVxMk6JtSnSQX9HMYvioRRkzvb46sQOJDn3Iu322IzBaaV18IKLx8FBR-QZ4RhjV4rYzqYu2K7J7ZVcVUoi0rx/s1600/00+Tweet.png" height="400" width="225" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Twitter ID가 없는 경우</td></tr>
</tbody></table>
아이디가 설정화면에서 정상적으로 설정이 되어 있으면, 아래와 같이 표시됩니다.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLfGExO5ZTTAqb-PGBcz-oHDxCbs29uRnBHZ113BtS9YejebgI182wSN96EZLFHgQLm4dhpZc-KrUIlyWf5PVlcLASObjK91MJByf5swqrZ-n-M8X94BDBkISDtyF1RydgTHwpO2CeJxI0/s1600/01+Tweet.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLfGExO5ZTTAqb-PGBcz-oHDxCbs29uRnBHZ113BtS9YejebgI182wSN96EZLFHgQLm4dhpZc-KrUIlyWf5PVlcLASObjK91MJByf5swqrZ-n-M8X94BDBkISDtyF1RydgTHwpO2CeJxI0/s1600/01+Tweet.png" height="400" width="225" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">설정된 트위터 아이디로 트윗을 작성중.</td></tr>
</tbody></table>
만약 작성 중에, 인터넷 연결이 끊기게 되면, 아래와 같이 Post를 하였을 때, 표시됩니다.<br />
개발자가 해준 부분은 없으며, 시스템에서 자동으로 표시하는 화면입니다.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIX7LDAeUaC_e7_qgCJ7Ymb9HSPhLE7T_Q6Os22FaiZLu5OSK4i1gxM-GKYySCI38eGMn66AosRH1yRI9vUv0GICcDFgYwTwCyA0i1S7V0Y5Dur88sphFdh8jI4nm5DjXjLpmoNxshYnNn/s1600/02+Tweet.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIX7LDAeUaC_e7_qgCJ7Ymb9HSPhLE7T_Q6Os22FaiZLu5OSK4i1gxM-GKYySCI38eGMn66AosRH1yRI9vUv0GICcDFgYwTwCyA0i1S7V0Y5Dur88sphFdh8jI4nm5DjXjLpmoNxshYnNn/s1600/02+Tweet.png" height="400" width="225" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">트윗을 보내지 못했을 때, 표시화면</td></tr>
</tbody></table>
위 화면이 표시될 경우에도, completionHandler에는 정상적으로 전송이 되었다고 결과 값을 리턴하게 되므로, 구분을 잘할 수 있어야 겠습니다.<br />
<br />
<h4>
참고:</h4>
트위터 개발자 센터 문서: <a href="https://dev.twitter.com/docs/ios">Integrating with Twitter on iOS</a><br />
Ray Wenderlich : <a href="http://www.raywenderlich.com/21558/beginning-twitter-tutorial-updated-for-ios-6">Beginning Twitter in iOS6 Tutorial</a><br />
<br />Davidhttp://www.blogger.com/profile/13155437116196860250noreply@blogger.com0tag:blogger.com,1999:blog-8138934057962831172.post-32305786692609244912014-05-12T07:16:00.003-07:002014-05-12T07:16:48.597-07:00[iOS] UIScrollView에서 현재 중심이 되는 페이지 얻어오기.ScrollView에서 페이지 단위로 뷰를 로딩해서 화면에 보여줄 경우, 현재 페이지의 앞뒤 페이지만 로딩하도록 해서 지금 필요한 페이지만 메모리를 사용할 수 있게 만들어야 됩니다.<br />
100페이지의 ScrollView라 할지라도, 현재는 3페이지만 로딩하도록 하는 것입니다.<br />
이 경우, 현재 페이지가 몇 페이지인지 알아야 합니다.<br />
<br />
페이지를 가로로 이동하는 경우에는, 페이지의 너비와 현재 페이지의 x좌표를 이용하여 알아낼 수 있습니다.<br />
<br />
사용자가 페이지를 터치해서 이동할 경우, scrollView.contentOffset.x 값이 변하게 됩니다.<br />
source code<br />
<pre class="brush:objc">- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGFloat pageWidth = self.scrollView.frame.size.width;
NSInteger page = (NSInteger)floor((self.scrollView.contentOffset.x * 2.0f + pageWidth) / (pageWidth * 2.0f));
NSLog(@"scrollView.contentOffset.x: %f, page:%d", scrollView.contentOffset.x, page);
}
</pre>
<br />
페이지를 왼쪽으로 이동시키다가, 현재 화면의 반을 넘어가는 경우, 다음 페이지가 되고, 오른쪽으로 이동시키다가 현재 페이지의 반 이하가 남게 되면, 이전 페이지로 인식해야 합니다.<br />
현재 페이지 = (x좌표 / 페이지너비 + 0.5)값의 반내림<br />
현재 페이지 = ((x좌표 + 1/2*페이지너비) / 페이지너비) 값의 반내림<br />
현재 페이지 = ((x좌표 + 페이지너비) / (2*페이지너비)) 값의 반내림
<br />
<br />
<pre class="brush:objc">- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGFloat pageWidth = self.scrollView.frame.size.width;
NSInteger page = (NSInteger)floor((self.scrollView.contentOffset.x * 2.0f + pageWidth) / (pageWidth * 2.0f));
NSLog(@"scrollView.contentOffset.x: %f, page:%d", scrollView.contentOffset.x, page);
}
</pre>
<br />
scrollView가 가로로 Scroll되었을 때, 현재 페이지를 알 수 있으므로, 페이지가 변경되면, 앞뒤 페이지를 로딩하여, 미리 준비하면 됩니다.<br />
<br />
<br />
[참조] : <a href="http://www.raywenderlich.com/10518/how-to-use-uiscrollview-to-scroll-and-zoom-content">http://www.raywenderlich.com/10518/how-to-use-uiscrollview-to-scroll-and-zoom-content</a><br />
<br />Davidhttp://www.blogger.com/profile/13155437116196860250noreply@blogger.com0tag:blogger.com,1999:blog-8138934057962831172.post-29296126385321635312014-05-12T06:39:00.004-07:002014-05-12T06:39:51.751-07:00[iOS] CALayer를 이용한 액자 모양 그림자 넣기.<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
기존의 CALayer를 이용해서, shadow를 설정할 수 있었습니다.<br />
그 방식에 shadowPath를 설정하여서 그림자의 모양을 변형하는 방법을 정리합니다.<br />
<br />
참조: <a href="http://nscookbook.com/2013/01/ios-programming-recipe-10-adding-a-shadow-to-uiview/">NSCookbook - iOS Programming Recipe 10: Adding A Shadow To UIView</a><br />
<br />
<br />
ViewController에 UIImageView를 하나 추가하고, 아래와 같이 설정을 합니다.<br />
source code<br />
<pre class="brush:objc"> CALayer *layer = self.imageView.layer;
layer.shadowOffset = CGSizeMake(1, 1);
layer.shadowColor = [[UIColor blackColor] CGColor];
layer.shadowRadius = 3.0f;
layer.shadowOpacity = 0.80f;
CGRect rect = self.imageView.frame;
CGSize size = rect.size;
CGFloat offset = 15.0f;
UIBezierPath *path = [UIBezierPath bezierPath]; //Path를 설정
[path moveToPoint:CGPointMake(0.0, offset)];
[path addLineToPoint:CGPointMake(size.width, offset)];
[path addLineToPoint:CGPointMake(size.width, size.height+offset)];
[path addCurveToPoint:CGPointMake(0.0, size.height+offset)
controlPoint1:CGPointMake(size.width-offset,size.height)
controlPoint2:CGPointMake(offset, size.height)];
[path closePath];
layer.shadowPath = [path CGPath];
</pre>
<br />
위의 shadowPath를 bezierPath로 만들어서 넣으면 그 Path를 따라서 그림자가 생기게 됩니다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1FEGoaud3GraUni1gCnoBu2DR3ncM82UcSrFi5W003fuJFva7tfz8B6vYL6GEMotXgP2MVhCp-igDzbEKAO-xA0HpTuyVz7tXISSoygxUbZugO0SlYJW7eViKXvEqFD0sA5zGeati8CZn/s1600/01.+ImageView.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><br /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1FEGoaud3GraUni1gCnoBu2DR3ncM82UcSrFi5W003fuJFva7tfz8B6vYL6GEMotXgP2MVhCp-igDzbEKAO-xA0HpTuyVz7tXISSoygxUbZugO0SlYJW7eViKXvEqFD0sA5zGeati8CZn/s1600/01.+ImageView.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><br /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1FEGoaud3GraUni1gCnoBu2DR3ncM82UcSrFi5W003fuJFva7tfz8B6vYL6GEMotXgP2MVhCp-igDzbEKAO-xA0HpTuyVz7tXISSoygxUbZugO0SlYJW7eViKXvEqFD0sA5zGeati8CZn/s1600/01.+ImageView.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1FEGoaud3GraUni1gCnoBu2DR3ncM82UcSrFi5W003fuJFva7tfz8B6vYL6GEMotXgP2MVhCp-igDzbEKAO-xA0HpTuyVz7tXISSoygxUbZugO0SlYJW7eViKXvEqFD0sA5zGeati8CZn/s1600/01.+ImageView.png" height="320" width="206" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-4p4HorwLkoq9mheKiNsI4fY9uJP2a8mMsBRuYrxuMUGzkOcbCD3vO84JZxfv8wahXpKORv_yzKeVgRya-A-zNwekxxuB_ipmUR5wd8AgGI0gvcX__AVKASH1VaqnGInfRPO4-pC8rBxn/s1600/02.+ImageView+with+shadow.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-4p4HorwLkoq9mheKiNsI4fY9uJP2a8mMsBRuYrxuMUGzkOcbCD3vO84JZxfv8wahXpKORv_yzKeVgRya-A-zNwekxxuB_ipmUR5wd8AgGI0gvcX__AVKASH1VaqnGInfRPO4-pC8rBxn/s1600/02.+ImageView+with+shadow.png" height="320" width="226" /></a></div>
<br />
[참고]<br />
이미지 URL: http://i.dailymail.co.uk/i/pix/2014/05/04/article-2620040-1D92597400000578-908_306x423.jpgDavidhttp://www.blogger.com/profile/13155437116196860250noreply@blogger.com0tag:blogger.com,1999:blog-8138934057962831172.post-19243081589134743842014-05-04T06:07:00.003-07:002014-05-04T06:07:44.667-07:00[iOS] TextView의 InnerShadow를 만들어 봅니다.TextView의 배경에 안쪽 그림자를 만들어봅니다.<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgiK6C5JC6osrs-bbAyfBB0OZt6XJKhvk2Bpszfm5Ul6cJMI6zfsmk9q4dOlrWaJWC_NOg6aE4DJPaWVOdTYVIwph-pgWbFtWCZ3RE12_7_Yv6KB4aBmZpTCWd2WuPmND5jOVc-iYj7-95B/s1600/00.+TextField+TextView+Inner+Shadow.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgiK6C5JC6osrs-bbAyfBB0OZt6XJKhvk2Bpszfm5Ul6cJMI6zfsmk9q4dOlrWaJWC_NOg6aE4DJPaWVOdTYVIwph-pgWbFtWCZ3RE12_7_Yv6KB4aBmZpTCWd2WuPmND5jOVc-iYj7-95B/s1600/00.+TextField+TextView+Inner+Shadow.png" height="305" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Inner Shadow가 적용된 화면</td></tr>
</tbody></table>
<br />
위의 그림처럼 TextView에서 InnerShadow를 이미지를 사용하지 않고 넣도록 합니다.<br />
<br />
<h4>
구현 방법은?</h4>
일단 배경이미지를 사용해서, 넣을 수도 있는데, 그렇게 되면, 메인 뷰의 배경이 변경이 되면 그것을 따라가지 못하고, 이미지의 색이 배경과 다르게 흰색 태두리가 생길 수 있습니다.<br />
그래서, CALayer를 이용해서, 그림자 효과로 만들어 봅니다.<br />
<br />
<h4>
- UIView에 대한 그림자 설정.</h4>
일단 일반적인 UIView의 CALayer에 그림자 설정과, 태두리를 둥글게 만들어 봅니다.<br />
source code<br />
<pre class="brush:objc"> UIView *view;
UIView *view;
view = self.testView; //코드를 설명을 위해서 대입함.
view.backgroundColor = [UIColor clearColor]; //배경을 투명하게 설정
view.layer.cornerRadius = 10.0f; //테두리 곡선이 되도록 설정 10.0f는 임의의 수
view.layer.borderColor = [UIColor whiteColor].CGColor; //테두리 색상 흰색
view.layer.borderWidth = 2.0f; //테두리 두께 2포인트
view.layer.shadowColor = [UIColor blackColor].CGColor; //그림자 검은색
view.layer.shadowOffset = CGSizeZero; //그림자 위치는 뷰의 위치와 동일
view.layer.shadowOpacity = 1.0f; //그림자 투명도
view.layer.shadowRadius = 3.0f; //그림자의 퍼지는 범위 클수록 넓게 그림자 생김.
</pre>
<br />
Storyboard에서 지정한 UITextField에 대해서 위와 같이 설정을 하면, 아래와 같이 표시가 됩니다.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCEYIS5VVX39r4ofsMCGN7cRQl7wzWCfdEwYOxpW-hQhyHIceYaKD30k5dulJRDP3xuqE0yv33LeWdc0nkVitaLyodbL3DwOtwMBjEJbFooOGI20QMR2RIXjIiCnBlRKxctiq78kNUIyjh/s1600/01.+UIView%E1%84%8B%E1%85%B4+%E1%84%80%E1%85%B3%E1%84%85%E1%85%B5%E1%86%B7%E1%84%8C%E1%85%A1+%E1%84%89%E1%85%A5%E1%86%AF%E1%84%8C%E1%85%A5%E1%86%BC.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCEYIS5VVX39r4ofsMCGN7cRQl7wzWCfdEwYOxpW-hQhyHIceYaKD30k5dulJRDP3xuqE0yv33LeWdc0nkVitaLyodbL3DwOtwMBjEJbFooOGI20QMR2RIXjIiCnBlRKxctiq78kNUIyjh/s1600/01.+UIView%E1%84%8B%E1%85%B4+%E1%84%80%E1%85%B3%E1%84%85%E1%85%B5%E1%86%B7%E1%84%8C%E1%85%A1+%E1%84%89%E1%85%A5%E1%86%AF%E1%84%8C%E1%85%A5%E1%86%BC.png" height="70" width="400" /></a></div>
위에서 코드를 추가합니다.<br />
source code<br />
<pre class="brush:objc"> view.layer.masksToBounds = YES; //바운드 외부로 나가는 것을 Mask처리함
</pre>
이렇게 하면 외부로 그림자가 나가는 것은 지워집니다.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzxL_t639GzoQlGgjlmYAmUuvZ4nu7E-Nng-rH_kQ6r-QLqqJOcsVECEJhf4sgfxVrV4xQ9zZoJm191AWj7gVDqH4Bt1dNu90Kqxe9DfsTo4gYH9hf6Bqnof1h1LB9vq3gxOUGU_Ge7h6T/s1600/02.+UIView%E1%84%8B%E1%85%B4+%E1%84%89%E1%85%A5%E1%86%AF%E1%84%8C%E1%85%A5%E1%86%BC.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzxL_t639GzoQlGgjlmYAmUuvZ4nu7E-Nng-rH_kQ6r-QLqqJOcsVECEJhf4sgfxVrV4xQ9zZoJm191AWj7gVDqH4Bt1dNu90Kqxe9DfsTo4gYH9hf6Bqnof1h1LB9vq3gxOUGU_Ge7h6T/s1600/02.+UIView%E1%84%8B%E1%85%B4+%E1%84%89%E1%85%A5%E1%86%AF%E1%84%8C%E1%85%A5%E1%86%BC.png" height="71" width="400" /></a></div>
<br />
이제 내부 테두리 비슷한 것이 설정이 되었습니다.<br />
이것을 UITextView에 적용을 하면 아래와 같아집니다.<br />
source code<br />
<pre class="brush:objc"> self.textView.backgroundColor = [UIColor clearColor];
view = self.textView; //UITextView로 변경하고 설정함.
view.backgroundColor = [UIColor clearColor];
view.layer.cornerRadius = 10.0f;
view.layer.borderColor = [UIColor whiteColor].CGColor;
view.layer.shadowColor = [UIColor blackColor].CGColor;
view.layer.borderWidth = 2.0f;
view.layer.shadowOffset = CGSizeZero;
view.layer.shadowOpacity = 1.0f;
view.layer.shadowRadius = 3.0f;
view.layer.masksToBounds = YES;
</pre>
<br />
설정은 UIView에 했던것과 동일하고, 이 설정을 TextView에 한 것입니다.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAALmDCZ112gPrh-fY2H8cBOC0ab2_nrgGnhbFZDOwsHkA-DXnWLhyyhSyLc4a1lOrPzH3yFrfpQpLTzty-F4l0i1XtNr9huw3FcXlFBV_1EsWeYa9rURS_iEdC0jRCWx5cVH5cCIyioxl/s1600/03.+UITextView%E1%84%8B%E1%85%A6+%E1%84%8C%E1%85%A5%E1%86%A8%E1%84%8B%E1%85%AD%E1%86%BC.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAALmDCZ112gPrh-fY2H8cBOC0ab2_nrgGnhbFZDOwsHkA-DXnWLhyyhSyLc4a1lOrPzH3yFrfpQpLTzty-F4l0i1XtNr9huw3FcXlFBV_1EsWeYa9rURS_iEdC0jRCWx5cVH5cCIyioxl/s1600/03.+UITextView%E1%84%8B%E1%85%A6+%E1%84%8C%E1%85%A5%E1%86%A8%E1%84%8B%E1%85%AD%E1%86%BC.png" height="213" width="320" /></a></div>
테두리에 그림자가 생기기는 했지만, 내부의 글자에도 그림자가 표시되는 문제가 발생합니다.<br />
이것을 어떻게 처리할 수가 없어서,<br />
TextView의 자리 배경에 UIView를 두어서 TextView의 주변에 inner shadow가 있는 것처럼 설정을 합니다.<br />
<br />
source code<br />
<pre class="brush:objc">-(void)drawInnerShadowOnViewForTextView:(UIView *)view color:(UIColor *)backgroundColor;
{
UIEdgeInsets insets = {-10, -15, +20, +30};
CGFloat cornerRadius = 18.5f;
CGFloat borderWidth = 2.0f;
CGFloat shadowRadius = 3.5f;
CGFloat shadowOpacity = 1.0f;
//그림자가 되는 View를 설정합니다.
UIView *innerShadowView = [[UIView alloc] initWithFrame:CGRectMake(view.frame.origin.x+insets.top, view.frame.origin.y+insets.left, view.frame.size.width + insets.bottom, view.frame.size.height+ insets.right)];
[innerShadowView setContentMode:UIViewContentModeScaleToFill];
[innerShadowView setAutoresizingMask : UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
[innerShadowView.layer setCornerRadius:cornerRadius]; //그림자의 가장자리 곡선
[innerShadowView.layer setMasksToBounds:YES];
[innerShadowView.layer setBorderColor: backgroundColor.CGColor]; //외부 배경을 테두리 색으로
[innerShadowView.layer setShadowColor:[UIColor blackColor].CGColor]; //그림자 색
[innerShadowView.layer setBorderWidth:borderWidth];
[innerShadowView.layer setShadowOffset:CGSizeMake(0, 0)];
[innerShadowView.layer setShadowOpacity:shadowOpacity];
[innerShadowView.layer setShadowRadius:shadowRadius];
[view.superview insertSubview:innerShadowView belowSubview:view];
}
</pre>
<br />
위와 같이 inner shadow 역할을 하는 UIView를 만들어서, TextView의 바로 아래에 설정을 합니다.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFRDUBSxqjDcPukr8uy4R8pOSwuRTylnEEMy1zz3NyE3MnJsOS4UmRLJNjhnQBkIKaV1FvZoxe4VCppXkJbgXTffSCFiq8ulQJo0NNB3uJJ4J4SSkgEK44MTOtsN1ceC5G8P797j0-zoOm/s1600/04.+UITextView%E1%84%8B%E1%85%B4+%E1%84%87%E1%85%A2%E1%84%80%E1%85%A7%E1%86%BC+%E1%84%89%E1%85%A5%E1%86%AF%E1%84%8C%E1%85%A5%E1%86%BC.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFRDUBSxqjDcPukr8uy4R8pOSwuRTylnEEMy1zz3NyE3MnJsOS4UmRLJNjhnQBkIKaV1FvZoxe4VCppXkJbgXTffSCFiq8ulQJo0NNB3uJJ4J4SSkgEK44MTOtsN1ceC5G8P797j0-zoOm/s1600/04.+UITextView%E1%84%8B%E1%85%B4+%E1%84%87%E1%85%A2%E1%84%80%E1%85%A7%E1%86%BC+%E1%84%89%E1%85%A5%E1%86%AF%E1%84%8C%E1%85%A5%E1%86%BC.png" height="253" width="400" /></a></div>
얼추 비슷하게 나왔습니다.<br />
헌데, View의 배경을 변경해 보면, 이상한 현상이 발생합니다.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjY-h2BvGTQ2w0_-f-YG-cf9-nqEgMvyR6Whm_mB4edg-puc8GXZjC1SL-iWdCK4Sb7TaNb_H0q_A8e8E-blv-_jGI1SvRTnMVs9yI7U45zAkC9X3mjxidPFwziHSPJ4Zov5FGAVlqXYXnH/s1600/05.+background+Color.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjY-h2BvGTQ2w0_-f-YG-cf9-nqEgMvyR6Whm_mB4edg-puc8GXZjC1SL-iWdCK4Sb7TaNb_H0q_A8e8E-blv-_jGI1SvRTnMVs9yI7U45zAkC9X3mjxidPFwziHSPJ4Zov5FGAVlqXYXnH/s1600/05.+background+Color.png" height="267" width="400" /></a></div>
<br />
inner shadow로 추가된 이미지 뒤에 같은 크기의 흰색 배경의 UIView를 추가해 줍니다.<br />
source code<br />
<pre class="brush:objc">-(void)drawInnerShadowOnViewForTextView:(UIView *)view color:(UIColor *)backgroundColor;
{
...위와 동일...
[innerShadowView.layer setShadowRadius:shadowRadius];
//추가 시작
UIView *innerBackgroundView = [[UIView alloc] initWithFrame:innerShadowView.frame];
[innerBackgroundView setBackgroundColor:[UIColor whiteColor]];
[innerBackgroundView.layer setCornerRadius:cornerRadius];
[innerBackgroundView.layer setBorderWidth:borderWidth];
[innerBackgroundView.layer setBorderColor:backgroundColor.CGColor];
[innerBackgroundView setAlpha:0.8f];
[view.superview insertSubview:innerBackgroundView belowSubview:view];
//추가 끝.
[view.superview insertSubview:innerShadowView belowSubview:view];
}
</pre>
뷰의 추가 위치가 textView 밑에 innerShadow, 그 밑에 innerBackView가 추가되어야 합니다.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQPnvg6S1iJgskJMQd6y4XpDS3VZ92XMd0LtYRRk0m_f2oCsgwRR6SqCITsqNmUZLIy6lBMkVc0rgKVGKlGfKH-cJfggEype9B33lIImFC1Fb5578nKQLyEQeiD2R_KdwMXwMKzBJDUbyh/s1600/06.+backgroundView+%E1%84%89%E1%85%A5%E1%86%AF%E1%84%8C%E1%85%A5%E1%86%BC.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQPnvg6S1iJgskJMQd6y4XpDS3VZ92XMd0LtYRRk0m_f2oCsgwRR6SqCITsqNmUZLIy6lBMkVc0rgKVGKlGfKH-cJfggEype9B33lIImFC1Fb5578nKQLyEQeiD2R_KdwMXwMKzBJDUbyh/s1600/06.+backgroundView+%E1%84%89%E1%85%A5%E1%86%AF%E1%84%8C%E1%85%A5%E1%86%BC.png" height="198" width="320" /></a></div>
위와 같이 표시가 됩니다.<br />
이제 배경색에 구애 받지 않고, 흰색으로 유지할 수 있습니다.<br />
<br />
그리고, 배경화면이 있을 경우에는, TextView와 innerBackView의 alpha를 변경해서, 아래와 같이 표시할 수도 있습니다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKGqmbJ2Jw7XdHNCkPDXeZutn7PortVDOxOuFNDNP0sDw0QCmzNs2hCKd7e7LO2U1OFRCaSEDszSgG7QUoYogicgRPRClOd8IY5cAFeI5boI3io7rHXr6UKtPjeVV3Ghn1noNLva0We1oO/s1600/07.+%E1%84%87%E1%85%A2%E1%84%80%E1%85%A7%E1%86%BC%E1%84%8B%E1%85%B5%E1%84%86%E1%85%B5%E1%84%8C%E1%85%B5+%E1%84%8C%E1%85%A5%E1%86%A8%E1%84%8B%E1%85%AD%E1%86%BC+%E1%84%87%E1%85%A1%E1%86%AB%E1%84%90%E1%85%AE%E1%84%86%E1%85%A7%E1%86%BC+%E1%84%89%E1%85%A5%E1%86%AF%E1%84%8C%E1%85%A5%E1%86%BC.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKGqmbJ2Jw7XdHNCkPDXeZutn7PortVDOxOuFNDNP0sDw0QCmzNs2hCKd7e7LO2U1OFRCaSEDszSgG7QUoYogicgRPRClOd8IY5cAFeI5boI3io7rHXr6UKtPjeVV3Ghn1noNLva0We1oO/s1600/07.+%E1%84%87%E1%85%A2%E1%84%80%E1%85%A7%E1%86%BC%E1%84%8B%E1%85%B5%E1%84%86%E1%85%B5%E1%84%8C%E1%85%B5+%E1%84%8C%E1%85%A5%E1%86%A8%E1%84%8B%E1%85%AD%E1%86%BC+%E1%84%87%E1%85%A1%E1%86%AB%E1%84%90%E1%85%AE%E1%84%86%E1%85%A7%E1%86%BC+%E1%84%89%E1%85%A5%E1%86%AF%E1%84%8C%E1%85%A5%E1%86%BC.png" height="248" width="320" /></a></div>
<br />
참고되시길 바랍니다.<br />
<br />
<br />
[참고]<br />
- StackOverflow: <a href="http://stackoverflow.com/questions/9783523/uiview-create-a-inner-shadow">UIView create a inner shadow</a><br />
<br />Davidhttp://www.blogger.com/profile/13155437116196860250noreply@blogger.com0tag:blogger.com,1999:blog-8138934057962831172.post-69197740729551881262014-05-01T06:27:00.001-07:002014-05-01T20:25:59.753-07:00[iOS] Custom TableViewCell의 Button을 통해, 현재 Cell의 indexPath를 알아내는 방법<br />
<br />
<h4>
1. IBAction 함수로 넘기는 sender의 point를 통해서 알아내는 방법</h4>
TableViewController에 IBAction함수를 정의하고, Cell에 있는 Button에서 Touch Up inside 이벤트에 대해서 TabelViewController의 아래 함수로 연결을 합니다.<br />
그러면, 특정 Cell에서 버튼이 클릭이 되면, 그 버튼객체를 sender로 해서 아래 함수가 호출이 됩니다.<br />
source code<br />
<pre class="brush:objc">- (IBAction) btnClicked:(id)sender
{</pre>
<pre class="brush:objc"> // (1)
CGPoint buttonPoint = [sender convertPoint:CGPointZero toView:self.tableView];</pre>
<pre class="brush:objc"> // 2.
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPoint];
if (indexPath != nil) {
//Found Cell
}
}
</pre>
(1) Cell 내에 있는 Button을 sender로 받고, 그 sender의 위치 포인트를 알아냅니다.<br />
- (CGPoint) convertPoint:(CGPoint)point toView:(UIView *)view<br />
: 자신의 좌표 체계에 있는 point 지점을 view의 좌표 체계에서 어느 지점인지 변환함.<br />
즉, Cell 내에 있는 Button의 특정 지점(0,0)을 TableView에서 어느 지점 인지 변환해서 TableView에서의 좌표로 변환을 합니다.<br />
(2) 그리고, 그 포인트에 해당하는 IndextPath를 찾기 위해서, UITableView의 - indexPathForRowAtPoint를 사용해서, 현재 포인트에 해당하는 indexPath를 구할 수 있습니다.<br />
<br />
<h4>
2. Cell 을 통해서 알아내는 방법</h4>
TableView의 함수 중에서 - indexPathForCell:(UITableCell*)를 이용할 수 도 있습니다.<br />
IBAction이벤트를 받은 함수에서 UITableCell을 가져올 수 있다면, 바로 indexPath를 찾을 수 있을 것입니다.<br />
하지만, 상위 View에서 UITableViewCell을 찾아서 이용해야 합니다.<br />
source code<br />
<pre class="brush:objc">- (IBAction) btnClicked:(id)sender
{
NSLog(@"btnClicked : %@", sender);
UIView *myView = sender;
UIView *superView = [myView superview];
while (superView != nil && ![superView isKindOfClass:[DBUTableViewCell class]]) {
myView = superView;
superView = [myView superview];
}
if (superView != nil) {
//찾았다.
NSIndexPath *indexPath = [self.tableView indexPathForCell:(UITableViewCell*)superView];
if (indexPath != nil) {
//이제 찾았다.
[_items removeObjectAtIndex:indexPath.row];
[self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
}
</pre>
<br />
위와 같이 받은 sender를 통해서 상위에 있는 UITableViewCell을 찾고, TableView의 indexPathForCell을 이용해서 알아 낼 수 있습니다.<br />
그러나, iOS6과 iOS7에서 TableViewCell의 구조가 조금 바뀌었기 때문에 달라질 수 있습니다.<br />
<br />
<br />
참고하시기 바랍니다.<br />
<br />
[참조]<br />
<a href="http://code.tutsplus.com/tutorials/blocks-and-table-view-cells-on-ios--mobile-22982">http://code.tutsplus.com/tutorials/blocks-and-table-view-cells-on-ios--mobile-22982</a><br />
<br />Davidhttp://www.blogger.com/profile/13155437116196860250noreply@blogger.com0