iOS

iOS Dev iOS Games

iOS swift: ขั้นตอนการสร้างแอปให้บันทึกข้อมูลแอปลงในไอคลาวด์

Enabling an iCloud container for app ID เปิดการใช้งานไอคลาวด์สำหรับแอปนั้นๆ

  1. Login to developer.apple.com
  2. หลักๆคือเมื่อมีการบันทึกข้อมูลใดๆในแอป ก็ให้บันทึกข้อมูลนั้นลงไอคลาวด์ด้วย ซึ่งปกติก็จะบันทึกข้อมูลด้วยไฟล์ โดยเราสร้างไฟล์ในแอปและแบคอัพไฟล์นั้นๆลงไอคลาวด์ไปพร้อมกันด้วย โดยข้อมูลของแอปในไอคลาวด์จะผูกกับบัญชีแอปเปิลไอดีของแอปนั้นๆ ซึ่งเมื่อมีการลบแอปและติดตั้งแอปใหม่หรือเปลี่ยนเครื่องใหม่ ก็ให้แอปดาวโหลดไฟล์นั้นๆจากไอคลาวด์มาไว้ในแอปเหมือนเดิม
  3. Create iCloud Container สร้างไอคลาวด์สำหรับแอปนั้นๆ
  4. ไปที่ Certificates, Identifiers & Profiles -> Identifiers กด ‘+’ เพื่อสร้างที่เก็บข้อมูลบนไอคลาวด์
    จากรายการ ให้เลือก iCloud Containers แล้วกดปุ่ม Continue ใส่คำอธิบาย description ที่เก็บข้อมูลบนไอคลาวด์ว่า iCloudBackup แล้วตั้งชื่อ identifier ให้สอดคล้องกับชื่อแอปจะได้จำง่าย เช่นถ้ามีแอปชื่อ CaptainLog ก็อาจจะตั้งชื่อว่า iCloud.com.yourdomain.CaptainLog กดปุ่ม Continue ตามรูป




  5. Register iCloud Container ลงทะเบียนชื่อพื้นที่เก็บข้อมูลบนไอคลาวด์
  6. กดปุ่ม Register เพื่อลงทะเบียน ข้อมูลชื่อพื้นที่เก็บข้อมูลจะเพิ่มในรายการของไแคลาวด์ ตามรูป


  7. Link app to iCloud Container เชื่อมโยงแอปนั้นๆกับพื้นที่เก็บข้อมูลในไอคลาวด์
  8. ไปที่ Certificates, Identifiers & Profiles กดเลือกแอปที่เราต้องการให้เก็บข้อมูลในไอคลาวด์
    ในรายการ Capabilities กดเลือก iCloud และกดปุ่ม Configure จากนั้นก็ให้เลือกชื่อพื้นที่เก็บข้อมูลไอคลาวด์เพื่อเชื่อมโยงกับแอป ตามรูป




    กด Save เราก็จะได้พื้นที่เก็บข้อมูลไอคลาวด์ที่เชื่อมโยงกับแอปของเรา

  9. enabling iCloud capabilities in Xcode เปิดการใช้งานไอคลาวด์ของแอปใน XCode
  10. เปิดแอปใน XCode กดแทป Signing & Capabilities ในโปรแจค กดปุ่ม ‘+’, ด้านบนเพิ่ม iCloud capability จากนั้นให้กดสองครั้ง Double click ตรงตัวเลือก iCloud ตามรูป




    กลับมาที่หน้า XCode Signing & Capabilities ให้เลือก iCloud Documents จาก Services และเลือกพื้นที่เก็บข้อมูลไอคลาวด์สำหรับแอปนั้นๆ ในกรณีนี้คือ iCloud.com.yourdomain.CaptainLog จาก Containers โดยพื้นที่เก็บข้อมูลไอคลาวด์ทั้งหมดที่เราสร้างขึ้นจากบัญชีนักพัฒนาในส่วน Certificates, Identifiers & Profiles จะมาปรากฎใน XCode ให้เราเลือกสำหรับแอปนั้นๆ ตามรูป

    เมื่อเรากำหนด iCloud Capabilities, XCode ก็จะสร้างไฟล์ชื่อ appname.entitlements ในโปรเจคเพื่อเก็บรายละเอียดของบริการไอคลาวด์ ตามรูป

  11. บันทึกข้อมูลแอปลงไอคลาวด์
  12. อันดับแรกต้องมีไฟล์ข้อมูลในแอป เช่นไฟล์ "myfile.plist" ซึ่งปกติแล้วเราจะสร้างไฟล์ข้อมูลสำหรับแอปไว้ในโฟลเดอร์ Documents จากนั้นให้คัดลอกข้อมูลจากแอปไปยังไอคลาวด์ หลักๆคือต้องหาเส้นทางไปยังโฟลเดอร์ของไฟล์ในแอป และไฟล์ในไอคลาวด์ ตามตัวอย่างฟังก์ชัน
        func saveToiCloud() throws {
            // กำหนดที่อยู่โฟลเดอร์ของไฟล์ในไอคลาวด์
            guard let containerURL = FileManager.default.url(forUbiquityContainerIdentifier: "iCloud.com.mtel.CaptainLog") else { return }
            // กำหนดที่อยู่โฟลเดอร์ของไฟล์ในแอป
            let docDirectory = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
            // กำหนดที่อยู่ของไฟล์ในแอป 
            if let fileURL = docDirectory?.appendingPathComponent("myfile.plist") {
                //  ถ้าโฟลเดอร์ยังไม่มี ให้สร้างโฟลเดอร์เก็บไฟล์ในไอคลาวด์
                if !FileManager.default.fileExists(atPath: containerURL.path) {
                    try FileManager.default.createDirectory(at: containerURL, withIntermediateDirectories: true, attributes: nil)
                }
                // กำหนดที่อยู่ของไฟล์ในไอคลาวด์
                let backupFileURL = containerURL.appendingPathComponent("myfile.plist")
                // ถ้ามีไฟล์เดิมอยู่แล้ว ให้ลบออก แล้วคัดลอกไฟฟล์ใหม่จากแอปไปแทนที่
                if FileManager.default.fileExists(atPath: backupFileURL.path) {
                    try FileManager.default.removeItem(at: backupFileURL)
                    try FileManager.default.copyItem(at: fileURL, to: backupFileURL)
                } else {
                    // ถ้าไฟล์ยังไม่มี ให้คัดลอกไฟฟล์ใหม่จากแอปไปเก็บในไอคลาวด์
                    try FileManager.default.copyItem(at: fileURL, to: backupFileURL)
                }
            }
        }
    

    ถ้าเขียนไฟล์ในไอคลาวด์สำเร็จ เราจะมองเห็นชื่อแอปในไอคลาวด์ของไอโฟนหรือไอแพด โดยไปที่ Apple ID -> iCloud -> Manage Storage -> Appname จะเห็นขนาดของพื้นที่ในไอคลาวด์ที่ใช้เก็บข้อมูลของแอปนั้นๆ
  13. ดาวโหลดข้อมูลจากไอคลาวด์มาลงแอป
  14. ขั้นตอนนี้ ทำย้อนกลับจากการบันทึก คือเราจะคัดลอกไฟล์จากไอคลาวด์ไปยังแอป เช่นเดียวกันคือต้องหาเส้นทางไปยังโฟลเดอร์ของไฟล์ในแอป และไฟล์ในไอคลาวด์
    โดยเมื่อมีการติดตั้งแอปใหม่ ก็ให้โหลดข้อมูลเดิมของแอปจากไอคลาวด์มาไว้ในแอป ตามตัวอย่างฟังก์ชัน โดยตอนเปิดแอปให้เช็คว่ามีไฟล์ข้อมูลในแอปแล้วยัง ถ้าไม่มีให้โหลดจากไอคลาวด์มาเก็บในแอป ซึ่งจะโหลดเพียงครั้งเดียวเท่านั้น เพราะหลังจากนั้นเราก็มีไฟล์ข้อมูลในแอปแล้ว โดยที่เมื่อไฟล์ข้อมูลแอปมีการเปลี่ยนแปลงก็ให้บันทึกลงไอคลาวด์ไปพร้อมๆกัน
    func loadFromiCloud() throws {
            let fileManager = FileManager.default
            // กำหนดที่อยู่โฟลเดอร์ของไฟล์ในไอคลาวด์
            guard let containerURL = fileManager.url(forUbiquityContainerIdentifier: "iCloud.com.mtel.CaptainLog") else { return }
            // กำหนดที่อยู่ของไฟล์ในไอคลาวด์
            if let icloudFileURL = containerURL.appendingPathComponent("myfile.plist") as URL? {
                // ดาวโหลดไฟล์จากไอคลาวด์
                try fileManager.startDownloadingUbiquitousItem(at: icloudFileURL)
                // กำหนดที่อยู่โฟลเดอร์ของไฟล์ในแอป
                let docDirectory = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
                // กำหนดที่อยู่ของไฟล์ในแอป ปกติจะเก็บข้อมูลแอปไว้ในโฟลเดอร์ Documents
                let fileURL = docDirectory?.appendingPathComponent("myfile.plist")
                var isDownloaded = false
                // วนลูป คอยให้ดาวโหลดเรียบร้อย
                print(icloudFileURL.path)
                print(fileURL.path)
                while !isDownloaded {
                  // ตรวจสอบว่าไฟล์ดาวโหลดมาแล้วหรือยัง
                    if fileManager.fileExists(atPath: icloudFileURL.path) {
                    isDownloaded = true
                  }
                }
                // ถ้าดาวโหลดเรียบร้อย ให้คัดลอกมาไว้ในแอป
                if isDownloaded {
                    do {
                        try FileManager.default.copyItem(at: icloudFileURL, to: fileURL!)
                    }
                    catch let error as NSError {
                        print(error.localizedDescription)
                    }
                }
                // นำไฟล์ข้อมูลไปใช้งาน ตัวอย่างนี้โหลดไฟล์ plist มาเก็บในดิกชันนารี แล้วแสดงผล
                if fileManager.fileExists(atPath: fileURL!.path) {
                    // read file
                    cash = NSDictionary(contentsOf: fileURL!) as! [String : String]
                    // get balance
                    let bal = cash["balance"]
                    cashBalance = Double(bal!)!
                    refreshBalance()
                    // remove balance key
                    cash.removeValue(forKey: "balance")
                    viewAll(self)
                    alert(text:"Done, import \(cash.count) items.\n")
                }
            }
    }
    

    ให้ทดลองสร้างข้อมูลในแอป จากนั้นก็ลบแอป (แต่ก่อนลบ ควรจะ export ไฟล์ข้อมูลไปเก็บไว้ที่อื่นก่อน เช่นใน Drive App หรือ Files App เผื่อผิดพลาด จะได้ import คืนมาได้) แล้วโหลดแอปใหม่ ข้อมูลเดิมจะโหลดจากไอคลาวด์มาแสดงผลเมื่อเปิดแอปครั้งแรก ในการเปิดแอปครั้งต่อไป จะไม่มีการดาวโหลด แต่จะอ่านจากไฟล์ที่อยู่ในแอปแทน
    แล้วทำไมไม่เขียนข้อมูลลงไอคลาวด์ไปเลย ไม่ต้องเก็บในแอป ซึ่งทำได้เหมือนกัน แต่ต้องโหลดจากไอคลาวด์ทุกครั้งที่เปิดแอป


iOS swift: การแชร์ข้อมูลไปยังแอปอื่น

iOS swift: Share image to other apps

@IBAction func shareImage(_ sender: Any) {
        let docDirectory = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
        if let fileURL = docDirectory?.appendingPathComponent("mypic.jpg") {
            let objectsToShare = [fileURL]
            let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
            // exclude apps you don't want to share to
			activityVC.excludedActivityTypes = [
                UIActivity.ActivityType.assignToContact,
                UIActivity.ActivityType.saveToCameraRoll,
                UIActivity.ActivityType.postToFlickr,
                UIActivity.ActivityType.postToVimeo,
                UIActivity.ActivityType.postToTencentWeibo,
                UIActivity.ActivityType.openInIBooks
            ]
			// if share to ipad, use popoverPresentationController to share
            if UIDevice.current.userInterfaceIdiom == .pad {
                if activityVC.responds(to: #selector(getter: UIViewController.popoverPresentationController)) {
                    activityVC.popoverPresentationController?.barButtonItem = sender as? UIBarButtonItem
                }
            }
            self.present(activityVC, animated: true, completion: nil)
        }
    }


iOS swift: Share string to other apps

@IBAction func shareString(_ sender: Any) {
        let word = "string to share"
        let objectsToShare = "\(word)"
            let activityVC = UIActivityViewController(activityItems: [objectsToShare], applicationActivities: nil)
            // exclude apps you don't want to share to
			activityVC.excludedActivityTypes = [
                UIActivity.ActivityType.assignToContact,
                UIActivity.ActivityType.saveToCameraRoll,
                UIActivity.ActivityType.postToFlickr,
                UIActivity.ActivityType.postToVimeo,
                UIActivity.ActivityType.postToTencentWeibo,
                UIActivity.ActivityType.openInIBooks
            ]
			// if share to ipad, use popoverPresentationController to share
            if UIDevice.current.userInterfaceIdiom == .pad {
                if activityVC.responds(to: #selector(getter: UIViewController.popoverPresentationController)) {
                    activityVC.popoverPresentationController?.barButtonItem = sender as? UIBarButtonItem
                }
            }
            self.present(activityVC, animated: true, completion: nil)
    }


iOS swift: Share file to other apps

@IBAction func shareFile(_ sender: Any) {
	let docDirectory = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
        if let fileURL = docDirectory?.appendingPathComponent("myfile.txt") {
            let objectsToShare = [fileURL]
            let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
            // exclude apps you don't want to share to
			activityVC.excludedActivityTypes = [
                UIActivity.ActivityType.assignToContact,
                UIActivity.ActivityType.saveToCameraRoll,
                UIActivity.ActivityType.postToFlickr,
                UIActivity.ActivityType.postToVimeo,
                UIActivity.ActivityType.postToTencentWeibo,
                UIActivity.ActivityType.postToTwitter,
                UIActivity.ActivityType.postToFacebook,
                UIActivity.ActivityType.openInIBooks
            ]
            // if share to ipad, use popoverPresentationController to share
            if UIDevice.current.userInterfaceIdiom == .pad {
                if activityVC.responds(to: #selector(getter: UIViewController.popoverPresentationController)) {
                    activityVC.popoverPresentationController?.barButtonItem = sender as? UIBarButtonItem
                }
            }
            self.present(activityVC, animated: true, completion: nil)
        }
    }

2020. mmunlin.com

:1066:42192142132026274421921421320262724421921421320262724