flutter build ios --config-only
입력(해당 과정까지 오류가 발생하지 않는다면?! 홈 화면 위젯 에서 새로 생성한 위젯을 찾을 수 있음.)
struct NewsArticleEntry: TimelineEntry {
let date: Date
let title: String
let description:String
}
기존의 SimpleEntry(원래 기본 홈위젯은 시간만 띄워줌) 를 우리가 원하는 정보(기사 제목, 기사 내용 등)를 띄워줄 NewsArticleEntry 로 바꾼다.
struct NewsWidgetsEntryView : View {
var entry: Provider.Entry
var body: some View {
VStack {
Text(entry.title)
Text(entry.description)
}
}
}
여기서는 뉴스 기사 제목, 내용 들을 띄우기 위해 VStack 수정
struct Provider: TimelineProvider {
// 위젯을 처음 생성할 때 예시로 보이는 부분.
func placeholder(in context: Context) -> NewsArticleEntry {
// Add some placeholder title and description, and get the current date
NewsArticleEntry(date: Date(), title: "Placeholder Title", description: "Placeholder description")
}
// 현재 시간과 상태(ex.사용자의 기본값 데이터)에 대한 부분.
func getSnapshot(in context: Context, completion: @escaping (NewsArticleEntry) -> ()) {
let entry: NewsArticleEntry
if context.isPreview{
entry = placeholder(in: context)
}
else{
// Get the data from the user defaults to display
let userDefaults = UserDefaults(suiteName: <YOUR APP GROUP>)
let title = userDefaults?.string(forKey: "headline_title") ?? "No Title Set"
let description = userDefaults?.string(forKey: "headline_description") ?? "No Description Set"
entry = NewsArticleEntry(date: Date(), title: title, description: description)
}
completion(entry)
}
// getTimeline is called for the current and optionally future times to update the widget
//콘텐츠를 업데이트 할 시점 고려할 시 도움을 주는 함수 (타임라인 항목 관련)
func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
// This just uses the snapshot function you defined earlier
// getSnapshot 함수를 통해서 현재 상태를 가져옴
getSnapshot(in: context) { (entry) in
// atEnd method 는 현재 시간이 지날 시 데이터를 새로고침 하도록 홈화면 위젯에 명령
let timeline = Timeline(entries: [entry], policy: .atEnd)
completion(timeline)
}
}
}
에러가 나지 않는다면? 정상적으로 작동한다.
struct NewsWidgetsEntryView : View {
...
// font url 을 쉽게 가져올 수 있도록 도움을 주는 함수
var bundle: URL {
let bundle = Bundle.main
if bundle.bundleURL.pathExtension == "appex" {
// Peel off two directory levels - MY_APP.app/PlugIns/MY_APP_EXTENSION.appex
var url = bundle.bundleURL.deletingLastPathComponent().deletingLastPathComponent()
url.append(component: "Frameworks/App.framework/flutter_assets")
return url
}
return bundle.bundleURL
}
// path를 통해서 폰트를 등록
init(entry: Provider.Entry){
self.entry = entry
CTFontManagerRegisterFontsForURL(bundle.appending(path: "/fonts/Chewy-Regular.ttf") as CFURL, CTFontManagerScope.process, nil)
}
...
}
var body: some View {
VStack {
// Update the following line.
Text(entry.title).font(Font.custom("Chewy", size: 13))
Text(entry.description).font(.system(size: 12)).padding(10)
}
}
//global key 생성 (해당 위젯의 크기를 가져오는데 필요한 context를 가져올때)
final _globalKey = GlobalKey();
String? imagePath;
...
floatingActionButton: FloatingActionButton.extended(
onPressed: () async {
if (_globalKey.currentContext != null) {
var path = await HomeWidget.renderFlutterWidget(
//home_widget package 에 있는 renderFlutterWidget 메소드를 통해서 LineChart()를 image화 한다.
const LineChart(),
/// fileName: 'screenshot', 이 부분은 실제로 사용을 안함. 변수 존재 x
key: 'filename',
logicalSize: _globalKey.currentContext!.size,//global key 사용
pixelRatio:
MediaQuery.of(_globalKey.currentContext!).devicePixelRatio,
);
setState(() {
imagePath = path as String?; //flutter위젯이 렌더링되는 image 위치 저장
});
}
updateHeadline(widget.article);
},
...
Center(
// New: Add this key 해당 currentContext 사용하기 위해서
key: _globalKey,
child: const LineChart(),
),
renderFlutterWidget 메소드가 호출 시
Xcode 에서 ios/NewsWidgets/NewsWidgets.swift 수정
struct NewsArticleEntry: TimelineEntry {
...
let date: Date
let title: String
let description:String
// New: add the filename and displaySize.
let filename: String
let displaySize: CGSize
}
새롭게 들어올 NewsArticleEntry 구조를 적어준다.
func placeholder(in context: Context) -> NewsArticleEntry {
NewsArticleEntry(date: Date(), title: "Placholder Title", description: "Placholder description", filename: "No screenshot available", displaySize: context.displaySize)
}
처음 홈화면위젯을 선택시에 보여지는 부분인 placeholder 를 수정한다.
struct NewsWidgetsEntryView : View {
...
// New: create the ChartImage view
var ChartImage: some View {
if let uiImage = UIImage(contentsOfFile: entry.filename) {
let image = Image(uiImage: uiImage)
.resizable()
.frame(width: entry.displaySize.height*0.5, height: entry.displaySize.height*0.5, alignment: .center)
return AnyView(image)
}
print("The image file could not be loaded")
return AnyView(EmptyView())
}
...
}
chartImage 가 보일 수 있도록 다음과 같이 코드를 추가해준다. 이때 크기는 frame의 50% 로 설정했다.
VStack {
Text(entry.title).font(Font.custom("Chewy", size: 13))
Text(entry.description).font(.system(size: 12)).padding(10)
// New: add the ChartImage to the NewsWidgetEntryView
ChartImage
}
Vstack 에 CharImage 를 추가해서 실제로 잘 동작 하는지 체크해보자.