Number: 037, Date: 2024-09-19

2024.09.09 ~ 2024.09.18

📷 Text OCR


Last week, after analyzing the reasons for the high recognition rate with the YesWeScan library, it turned out that the recognition rate was poor when casting AVCapturePhoto to UIImage, but it improved significantly when using CMSampleBuffer cast to CIImage.

Additionally, to handle automatic text recognition without manually triggering capture actions, I found that by using AVCaptureVideo instead of AVCapturePhoto, I could input each frame and cast the received CMSampleBuffer to CIImage. This way, text recognition through Vision could automatically process cases when text was recognized.

🌎 YouTube Data API Utilization - Fetching Videos from Playlist


Last week, I wrote a Python script to fetch video lists from a specific YouTube channel.

When the number of videos from a specific channel is very large, there are limits on the free API usage, so even if a delay is specified, it may not fetch all videos. Additionally, if there are separate videos in a playlist, I also created a script to fetch the video list from the playlist.

🔗 YouTube API Docs - playlistitem

import requests
import time

# Step 1: API Settings
API_KEY = ''  # Enter your actual API key here
PLAYLIST_ID = ''  # Playlist ID
CHANNEL_ID = ''  # Channel ID to fetch titles from

MAX_RESULTS = 50  # Maximum number of results to fetch at once (up to 50)

# Base URL for YouTube Data API v3 playlistItems endpoint
youtube_url = 'https://www.googleapis.com/youtube/v3/playlistItems'

# Parameters required for the API request
params = {
    'part': 'snippet',
    'maxResults': MAX_RESULTS,
    'playlistId': PLAYLIST_ID,
    'key': API_KEY
}

# Function to fetch video titles and URLs from the playlist
def fetch_playlist_video_titles_and_urls():
    videosResult = []
    next_page_token = None
    index = 1  # Starting index for videos

    while True:
        if next_page_token:
            params['pageToken'] = next_page_token

        # Step 2: Send GET request to YouTube Data API
        response = requests.get(youtube_url, params=params)
        data = response.json()

        # Step 3: Extract video titles and URLs
        for item in data['items']:
            title = item['snippet']['title']
            video_id = item['snippet']['resourceId']['videoId']
            video_url = f'https://www.youtube.com/watch?v={video_id}&list={PLAYLIST_ID}&index={index}'
            videosResult.append((title, video_url))
            index += 1

        # Check if there's a next page
        next_page_token = data.get('nextPageToken')

        # Wait 61 seconds if there's a next page
        if not next_page_token:
            break

    return videosResult

# Function to save titles and URLs to a text file
def save_titles_and_urls_to_file(videos, filename='playlist_video_titles_and_urls.txt'):
    with open(filename, 'w', encoding='utf-8') as file:
        for index, (title, url) in enumerate(videos, start=1):
            file.write(f"{index}. **[{title}]({url})**\n\n")

# Execute the code
videos = fetch_playlist_video_titles_and_urls()
save_titles_and_urls_to_file(videos)

👨‍🎓 AuthorizationStatus Overview


In iOS, some systems require permission to access certain features. For example, if location permission is needed, you must have permission to access location information.

You can determine the status of permissions using an enum object called AuthorizationStatus.

For location access, it varies slightly with CLAuthorizationStatus, but most cases fall into three categories that are frequently used: (Authorized, Denied, NotDetermined).

The NotDetermined state indicates that permission has not been requested. However, there can be instances where it remains NotDetermined even after the app prompts for permission when it first starts, which was puzzling, and I found only information about potential errors when searching.

When making permission requests in a closure, it is important to ensure that UI-related tasks are performed on the main thread.

🙋🏻‍♂️ Other Notes


  1. After the announcement of Xcode 16, I was curious about the differences from previous versions and found it interesting that Xcode was announced before iOS and is exclusive to macOS.
  2. A simple way to use regular expressions is that [A-Z0-91{2}_[A-Z0-9]{2}_[A-Z0-9]{2} and ([A-Z0-9]{2}_){2}[A-Z0-9]{2} are identical.
  3. How to handle animations when the keyboard appears while implementing layouts with SnapKit.
    @objc func keyboardWillShow(note: NSNotification) {
        if let keyboardSize = (note.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
            var keyboardHeight = CGFloat(Int(keyboardSize.height))
            
            self.scrollView.snp.updateConstraints {
                $0.bottom.equalToSuperView().offset(-keyboardHeight)
            }
    
            UIView.animate(withDuration: 0.5, delay: 0, options: .curveEaseOut, animations: {
                self.view.layoutIfNeeded()
            }, completion: nil)
        }
    }
    
  4. I organized Xcode shortcuts.
  5. I found a well-organized site on SwiftUI called Kavsoft and organized my notes using that channel.
  6. I organized methods that were not frequently used in the level 0 coding test on Programmers.