普通视图

发现新文章,点击刷新页面。
今天 — 2026年5月11日首页

每日一题-分割数组中数字的数位🟢

2026年5月11日 00:00

给你一个正整数数组 nums ,请你返回一个数组 answer ,你需要将 nums 中每个整数进行数位分割后,按照 nums 中出现的 相同顺序 放入答案数组中。

对一个整数进行数位分割,指的是将整数各个数位按原本出现的顺序排列成数组。

  • 比方说,整数 10921 ,分割它的各个数位得到 [1,0,9,2,1] 。

 

示例 1:

输入:nums = [13,25,83,77]
输出:[1,3,2,5,8,3,7,7]
解释:
- 分割 13 得到 [1,3] 。
- 分割 25 得到 [2,5] 。
- 分割 83 得到 [8,3] 。
- 分割 77 得到 [7,7] 。
answer = [1,3,2,5,8,3,7,7] 。answer 中的数字分割结果按照原数字在数组中的相同顺序排列。

示例 2:

输入:nums = [7,1,3,9]
输出:[7,1,3,9]
解释:nums 中每个整数的分割是它自己。
answer = [7,1,3,9] 。

 

提示:

  • 1 <= nums.length <= 1000
  • 1 <= nums[i] <= 105

2553. 分割数组中数字的数位

作者 stormsunshine
2024年1月28日 13:37

解法

思路和算法

这道题要求将给定的正整数数组 $\textit{nums}$ 中的所有正整数按数位分割,保持数位顺序存入答案数组。需要首先遍历数组 $\textit{nums}$ 得到数位总数,然后将每个正整数按数位分割并存入答案数组。

首先遍历数组 $\textit{nums}$ 得到所有正整数的数位总数 $\textit{totalLength}$,然后创建长度为 $\textit{totalLength}$ 的答案数组 $\textit{answer}$,再次遍历数组 $\textit{nums}$,遍历过程中维护答案数组的当前下标 $\textit{index}$,对于每个正整数,执行如下操作。

  1. 用 $\textit{start}$ 表示当前正整数的数位填入答案数组的起始下标,$\textit{start} = \textit{index}$。

  2. 每次将 $\textit{num}$ 的最低位填入 $\textit{answer}[\textit{index}]$,然后将 $\textit{index}$ 的值增加 $1$,重复该操作直到 $\textit{num}$ 的所有位都填入答案数组。

  3. 当前正整数 $\textit{num}$ 填入答案数组的下标范围是 $[\textit{start}, \textit{index} - 1]$,为按照数位从低到高的顺序填入。为了和数组 $\textit{nums}$ 中的数位顺序保持一致,需要将答案数组的下标范围 $[\textit{start}, \textit{index} - 1]$ 的子数组翻转。

遍历结束之后,即可得到答案数组。

代码

###Java

class Solution {
    public int[] separateDigits(int[] nums) {
        int totalLength = 0;
        for (int num : nums) {
            totalLength += getLength(num);
        }
        int[] answer = new int[totalLength];
        int index = 0;
        for (int num : nums) {
            int start = index;
            int temp = num;
            while (temp != 0) {
                answer[index] = temp % 10;
                index++;
                temp /= 10;
            }
            reverse(answer, start, index - 1);
        }
        return answer;
    }

    public int getLength(int num) {
        int length = 0;
        while (num != 0) {
            length++;
            num /= 10;
        }
        return length;
    }

    public void reverse(int[] answer, int start, int end) {
        for (int i = start, j = end; i < j; i++, j--) {
            int temp = answer[i];
            answer[i] = answer[j];
            answer[j] = temp;
        }
    }
}

###C#

public class Solution {
    public int[] SeparateDigits(int[] nums) {
        int totalLength = 0;
        foreach (int num in nums) {
            totalLength += GetLength(num);
        }
        int[] answer = new int[totalLength];
        int index = 0;
        foreach (int num in nums) {
            int start = index;
            int temp = num;
            while (temp != 0) {
                answer[index] = temp % 10;
                index++;
                temp /= 10;
            }
            Reverse(answer, start, index - 1);
        }
        return answer;
    }

    public int GetLength(int num) {
        int length = 0;
        while (num != 0) {
            length++;
            num /= 10;
        }
        return length;
    }

    public void Reverse(int[] answer, int start, int end) {
        for (int i = start, j = end; i < j; i++, j--) {
            int temp = answer[i];
            answer[i] = answer[j];
            answer[j] = temp;
        }
    }
}

###C++

class Solution {
public:
    vector<int> separateDigits(vector<int>& nums) {
        int totalLength = 0;
        for (int num : nums) {
            totalLength += getLength(num);
        }
        vector<int> answer(totalLength);
        int index = 0;
        for (int num : nums) {
            int start = index;
            int temp = num;
            while (temp != 0) {
                answer[index] = temp % 10;
                index++;
                temp /= 10;
            }
            reverse(answer, start, index - 1);
        }
        return answer;
    }

    int getLength(int num) {
        int length = 0;
        while (num != 0) {
            length++;
            num /= 10;
        }
        return length;
    }

    void reverse(vector<int>& answer, int start, int end) {
        for (int i = start, j = end; i < j; i++, j--) {
            swap(answer[i], answer[j]);
        }
    }
};

###Python

class Solution:
    def separateDigits(self, nums: List[int]) -> List[int]:
        answer = []
        index = 0
        for num in nums:
            start = index
            temp = num
            while temp != 0:
                answer.append(temp % 10)
                index += 1
                temp //= 10
            self.reverse(answer, start, index - 1)
        return answer

    def getLength(self, num: int) -> int:
        length = 0
        while num != 0:
            length += 1
            num //= 10
        return length

    def reverse(self, answer: List[int], start: int, end: int) -> None:
        i, j = start, end
        while i < j:
            answer[i], answer[j] = answer[j], answer[i]
            i += 1
            j -= 1

###C

int getLength(int num) {
    int length = 0;
    while (num != 0) {
        length++;
        num /= 10;
    }
    return length;
}

void reverse(int* answer, int start, int end) {
    for (int i = start, j = end; i < j; i++, j--) {
        int temp = answer[i];
        answer[i] = answer[j];
        answer[j] = temp;
    }
}

int* separateDigits(int* nums, int numsSize, int* returnSize) {
    int totalLength = 0;
    for (int i = 0; i < numsSize; i++) {
        totalLength += getLength(nums[i]);
    }
    int* answer = (int*) malloc(sizeof(int) * totalLength);
    *returnSize = totalLength;
    int index = 0;
    for (int i = 0; i < numsSize; i++) {
        int start = index;
        int temp = nums[i];
        while (temp != 0) {
            answer[index] = temp % 10;
            index++;
            temp /= 10;
        }
        reverse(answer, start, index - 1);
    }
    return answer;
}

###Go

func separateDigits(nums []int) []int {
    totalLength := 0
    for _, num := range nums {
        totalLength += getLength(num)
    }
    answer := make([]int, totalLength)
    index := 0
    for _, num := range nums {
        start := index
        temp := num
        for temp != 0 {
            answer[index] = temp % 10
            index++
            temp /= 10
        }
        reverse(answer, start, index - 1)
    }
    return answer
}

func getLength(num int) int {
    length := 0
    for num != 0 {
        length++
        num /= 10
    }
    return length
}

func reverse(answer []int, start int, end int) {
    for i, j := start, end; i < j; i, j = i + 1, j - 1 {
        answer[i], answer[j] = answer[j], answer[i]
    }
}

###JavaScript

var separateDigits = function(nums) {
    let totalLength = 0;
    for (let num of nums) {
        totalLength += getLength(num);
    }
    let answer = new Array(totalLength);
    let index = 0;
    for (let num of nums) {
        let start = index;
        let temp = num;
        while (temp !== 0) {
            answer[index] = temp % 10;
            index++;
            temp = Math.floor(temp / 10);
        }
        reverse(answer, start, index - 1);
    }
    return answer;
};

var getLength = function(num) {
    let length = 0;
    while (num !== 0) {
        length++;
        num = Math.floor(num / 10);
    }
    return length;
};

var reverse = function(answer, start, end) {
    for (let i = start, j = end; i < j; i++, j--) {
        let temp = answer[i];
        answer[i] = answer[j];
        answer[j] = temp;
    }
};

###TypeScript

function separateDigits(nums: number[]): number[] {
    let totalLength = 0;
    for (let num of nums) {
        totalLength += getLength(num);
    }
    let answer = new Array(totalLength);
    let index = 0;
    for (let num of nums) {
        let start = index;
        let temp = num;
        while (temp !== 0) {
            answer[index] = temp % 10;
            index++;
            temp = Math.floor(temp / 10);
        }
        reverse(answer, start, index - 1);
    }
    return answer;
};

function getLength(num: number): number {
    let length = 0;
    while (num !== 0) {
        length++;
        num = Math.floor(num / 10);
    }
    return length;
};

function reverse(answer: number[], start: number, end: number): void {
    for (let i = start, j = end; i < j; i++, j--) {
        let temp = answer[i];
        answer[i] = answer[j];
        answer[j] = temp;
    }
};

复杂度分析

  • 时间复杂度:$O(n \log_{10} m)$,其中 $n$ 是数组 $\textit{nums}$ 的长度,$m$ 是数组 $\textit{nums}$ 的最大元素。计算答案数组的长度与将数位填入答案数组的时间是 $O(n \log_{10} m)$。

  • 空间复杂度:$O(1)$。注意返回值不计入空间复杂度。

倒序插入

2023年3月9日 13:24

这个刚开始写的时候担心数组的长度和时间复杂度的原因,担心通过不了,结果没想过通过了。
我是用一个result数组来装将返回的分割数位值,考虑他们的长度,每一个元素的大小在10的五次方以内,分割之后100000共有六位,也就是最大是6,加上数组的长度最大是1000,于是我就把数组的大小取为6*10000=60000.
虽然我也知道浪费空间,但是我目前没有更好的方法,希望有大佬能够指点。

确定了返回数组了,然后就是然后把原始的整数拆分插入到结果数组中,后面我想到只要逐个不断求余就可以得到每一位数,后面我就在第一层遍历中添加一个循环得到整数的各个数位,但是提交的结果不符合要求,题目要求将数位按原本出现的顺序排列成数组,于是我就用一个数组作为辅助空间,将它反向添加,于是就得到了和题目意思相同的结果,辅助空间的大小就是一个整数拥有的各个位数的数量,由前面可以知道最大是6。

之后返回即可。

int* separateDigits(int* nums, int numsSize, int* returnSize){
    int *result=(int*)malloc(sizeof(int)*60000);
    int count=0;
    //遍历整个数组
    for(int i=0;i<numsSize;i++){
        int tmp=nums[i];
        int help[6];
        int tmpCount=0;
        //得到整数的各个数位,将他们储存在一个辅助数组中
        while(tmp){
            help[tmpCount++]=tmp%10;
            tmp=tmp/10;
        }
        //把数组中的元素倒序添加到结果数组中
        for(int j=tmpCount-1;j>=0;j--){
            result[count++]=help[j];
        }
    }
    *returnSize=count;
    return result;
}

两种方法:用字符串 / 不用字符串(Python/Java/C++/Go)

作者 endlesscheng
2023年2月5日 00:16

写法一:用字符串

把 $\textit{nums}[i]$ 转成字符串,即可从高到低遍历数位。

class Solution:
    def separateDigits(self, nums: List[int]) -> List[int]:
        return [int(ch) for x in nums for ch in str(x)]
class Solution {
    public int[] separateDigits(int[] nums) {
        List<Integer> digits = new ArrayList<>();
        for (int x : nums) {
            for (char ch : String.valueOf(x).toCharArray()) {
                digits.add(ch - '0');
            }
        }

        int m = digits.size();
        int[] ans = new int[m];
        for (int i = 0; i < m; i++) {
            ans[i] = digits.get(i);
        }
        return ans;
    }
}
class Solution {
public:
    vector<int> separateDigits(vector<int>& nums) {
        vector<int> ans;
        for (int x : nums) {
            for (char ch : to_string(x)) {
                ans.push_back(ch - '0');
            }
        }
        return ans;
    }
};
func separateDigits(nums []int) (ans []int) {
for _, x := range nums {
for _, ch := range strconv.Itoa(x) {
ans = append(ans, int(ch-'0'))
}
}
return
}

复杂度分析

  • 时间复杂度:$\mathcal{O}(n\log U)$,其中 $n$ 是 $\textit{nums}$ 的长度,$U=\max(\textit{nums})$。
  • 空间复杂度:$\mathcal{O}(\log U)$。返回值不计入。

方法二:不用字符串

不断地把 $n$ 除以 $10$(下取整)直到 $0$,例如 $123\to 12\to 1\to 0$。在这个过程中的 $n\bmod 10$,即为每个数位。

这样做是从低到高遍历数位,和题目要求的顺序相反。

我们可以从右到左遍历 $\textit{nums}$,从低到高遍历 $\textit{nums}[i]$ 的数位。最后把遍历过的数位反转,即为答案。

class Solution:
    def separateDigits(self, nums: list[int]) -> list[int]:
        ans = []
        for x in reversed(nums):
            while x > 0:
                ans.append(x % 10)
                x //= 10
        ans.reverse()
        return ans
class Solution {
    public int[] separateDigits(int[] nums) {
        List<Integer> digits = new ArrayList<>();
        for (int i = nums.length - 1; i >= 0; i--) {
            for (int x = nums[i]; x > 0; x /= 10) {
                digits.add(x % 10);
            }
        }

        int m = digits.size();
        int[] ans = new int[m];
        for (int i = 0; i < m; i++) {
            ans[i] = digits.get(m - 1 - i);
        }
        return ans;
    }
}
class Solution {
public:
    vector<int> separateDigits(vector<int>& nums) {
        vector<int> ans;
        for (int x : nums | views::reverse) {
            for (; x > 0; x /= 10) {
                ans.push_back(x % 10);
            }
        }
        ranges::reverse(ans);
        return ans;
    }
};
func separateDigits(nums []int) (ans []int) {
for _, x := range slices.Backward(nums) {
for ; x > 0; x /= 10 {
ans = append(ans, x%10)
}
}
slices.Reverse(ans)
return
}

复杂度分析

  • 时间复杂度:$\mathcal{O}(n\log U)$,其中 $n$ 是 $\textit{nums}$ 的长度,$U=\max(\textit{nums})$。
  • 空间复杂度:$\mathcal{O}(1)$。返回值不计入。

分类题单

如何科学刷题?

  1. 滑动窗口与双指针(定长/不定长/单序列/双序列/三指针/分组循环)
  2. 二分算法(二分答案/最小化最大值/最大化最小值/第K小)
  3. 单调栈(基础/矩形面积/贡献法/最小字典序)
  4. 网格图(DFS/BFS/综合应用)
  5. 位运算(基础/性质/拆位/试填/恒等式/思维)
  6. 图论算法(DFS/BFS/拓扑排序/基环树/最短路/最小生成树/网络流)
  7. 动态规划(入门/背包/划分/状态机/区间/状压/数位/数据结构优化/树形/博弈/概率期望)
  8. 常用数据结构(前缀和/差分/栈/队列/堆/字典树/并查集/树状数组/线段树)
  9. 数学算法(数论/组合/概率期望/博弈/计算几何/随机算法)
  10. 贪心与思维(基本贪心策略/反悔/区间/字典序/数学/思维/脑筋急转弯/构造)
  11. 链表、树与回溯(前后指针/快慢指针/DFS/BFS/直径/LCA)
  12. 字符串(KMP/Z函数/Manacher/字符串哈希/AC自动机/后缀数组/子序列自动机)

我的题解精选(已分类)

欢迎关注 B站@灵茶山艾府

昨天 — 2026年5月10日首页

FreshRSS 1.29.0

作者 Alkarex
2026年5月10日 22:43

This is a major release.

Feature highlights✨:

  • New sort order preferences at global, category, and feed levels
  • Use feed-provided icon
  • New option to hide sidebar by default
  • Show time since when a feed has problems
  • New functions to handle plural in internationalisation
  • New cli/purge.php to apply purge policy from command line

Bug fixes highlights 🐛:

  • Improve support of PHP 8.5+
  • Several fixes related to searches

Security highlights 🛡:

  • Limit cURL to protocols HTTP, HTTPS

UI highlights 🖼:

  • Improve mobile view with multiple lines when thumbnails and summaries are shown
  • Several themes improved

Extensions highlights 🧩:

  • New Webhook extension for automated RSS notifications
  • New LLM Classification extension to automatically tag incoming articles based on a prompt sent to an LLM

This release has been made by @Alkarex, @Inverle, @Kiblyn11, @math-GH, @rupakbajgain, @xtmd and newcomers @polybjorn, @olivluca, @tomasodehnal, @PeterVavercak, @mrtnrdl, @ale-rt, @cweiske, @rid3r45, @gabbihive, @drosell271, @Kachelkaiser, @zanivann, @nanos, @bowencool, @pe1uca, @matheusroberson, @DenuxPlays, @rlrs, @chanse-syres, @IEEE-754, @umaidshahid, @michi-onl

Full changelog:

  • Features
    • New sort order preferences at global, category, and feed levels #8234
    • New filtering by date of Server modification date #8131, #8576
      • Corresponding search operator, e.g. mdate:P1D for finding articles modified by the author / server during the past day.
      • Especially useful for optimising the API synchronisation.
    • Use feed-provided icon #8633
    • New option to automatically mark new articles as read if an identical GUID already exists in the same category #8673
    • Automatic feed visibility/priority during search #8609
    • Add feed visibility filter to statistics view unread dates #8489
    • Add option to enable/disable notifications, also for PWA #8458
    • Add a form to create new user queries on the User Queries page #8623
    • Allow WebSub hub push from same private network #8450
    • Support category field in JSON feed import #8786
  • Bug fixing
    • Fix wrong search toString in case of regex-looking string #8479
    • Fix article last seen date in case of feed errors #8646
    • Fix search expansion with backslash #8497
    • Fix user query parsing #8543
    • Fix search in shared user queries #8789
    • Fix redirect to wrong view after mark as read in reader and global views #8552
    • Fix SQLite paging when sorting by article length #8594
    • Fix change sorting during paging #8688
    • Fix SQL keyset pagination when sorting by category name #8597
    • Fix SQL duplicates in the user labels when sorting randomly #8626
    • Fix wrong error redirect in subscription management #8625
    • Fix do not include hidden feeds when counting total number of unread articles #8715
    • Update user modify date when changing extensions UserJS / UserCSS #8607
    • Non-strict OPML export #eedefb
  • Security
    • Limit cURL to protocols HTTP, HTTPS #8713
    • Better sanitise favicon URLs #8714
    • New setting for <iframe> referrer allow list #8672
    • Fix email validation and allow error page for unverified email users #8582
    • Add allowfullscreen to <iframe> #8467
    • Rewrite Set-Cookie using native PHP support of SameSite #8447, #8778
      • Sanitize lifetime of session cookies from session.cookie-lifetime in php.ini
    • Update to <meta name="referrer" content="no-referrer" /> from deprecated never #8725
    • Preventive measure against search ingestion #8777
  • UI
    • New option to hide sidebar by default #8528
    • Improve mobile view with multiple lines when thumbnails and summaries are shown #8631
    • New option to disable unread counter in tab title and favicon #8728
    • Show time since when a feed has problems #8670
    • Improve add feed UI #8683
    • Improve slider behaviour when using navigate back button #8496, #8524
    • Improve consistency of slider behaviour after submitting form #8612
    • Create dynamic favicons from SVG instead of PNG canvas #8577, #8588
    • Only display scrollbar everywhere if there's an overflow (especially for Chromium) #8542
    • Fix CSS padding of .content pre code #8620
    • Fix wrong navigation buttons layout on Chromium #8606
    • Fix don’t mark as read if middle click is outside of article link #8553
    • More robust JS #8595
    • Fix sidebar slide animation at narrow viewports #8747
    • Visually dim disabled users in user management table #8768
    • Improve multiple UI themes #8711, #8732,
      #8733, #8734, #8735,
      #8736, #8737, #8738,
      #8739, #8743, #8746,
      #8749, #8761, #8781,
      #8784, #8785
    • Various UI and style improvements: #8537, #8538,
      #8541, #8624, #8731,
      #8774
  • Deployment
    • Also push Docker images to GitHub registry #8669
    • Improve support of PHP 8.5+ using Pdo\Mysql #8526
    • Add support for Podman in Makefile #8456
    • Re-add database status in installation check #8510
    • Docker / CLI: Allow chown/chmod to fail with warning #8635
  • Extensions
    • New Webhook extension for automated RSS notifications Extensions#456
    • New LLM Classification extension to automatically tag incoming articles based on a prompt sent to an LLM Extensions#458
    • New extension methods to get typed configuration values #8696
    • New hook: Minz_HookType::ActionExecute #8599, #8603
    • New hook to modify the list of feeds to actualize #8655, #8675
    • Allow passing Minz_HookType as hook name in registerHook() #8600
    • Return more info and status from httpGet() #8700
    • Make httpGet() cache nullable #8705
    • Allow extensions’ configuration UI to use select-input-changer JavaScript helper #8721
  • SimplePie
  • CLI
    • New cli/purge.php to apply purge policy #8740
  • I18n
  • Misc.

老司机 iOS 周报 #370 | 2026-05-11

作者 ChengzhiHuang
2026年5月10日 22:13

ios-weekly
老司机 iOS 周报,只为你呈现有价值的信息。

你也可以为这个项目出一份力,如果发现有价值的信息、文章、工具等可以到 Issues 里提给我们,我们会尽快处理。记得写上推荐的理由哦。有建议和意见也欢迎到 Issues 提出。

新闻

🐕 DanceUI 开源

@Kyle-Ye: DanceUI 是 ByteDance 开源的类 SwiftUI 声明式 UI 框架,目标是在 SwiftUI 风格的 DSL 和更低系统版本兼容之间做一层工程化实现。项目提供了与 SwiftUI 对齐的基础能力,包括 StateBindingEnvironmentPreferenceKeyNavigationViewScrollView 等,同时通过 DanceUIRuntime、DanceUIGraph、OpenCombine 和 DanceUIObservation 相关模块支撑状态更新与渲染链路。整体预期是可以直接复用 SwiftUI 生态且最低支持 iOS 13。

文章

🐢 Trust, Then Verify

@Cooper Chen:以这篇文章《Trust, Then Verify》开头,你会很快意识到 : 真正拉开 AI 编程差距的,不是“写得快”,而是“能自证”。作者围绕 iOS 场景搭建了一套完整验证闭环 : 构建侧用 xcodebuild + xcbeautify 控噪并保留原始日志兜底,交互侧用 AXe 与 simctl 将启动、点击、读值、断言流程脚本化,让 Agent 从“像是对了”走向“可验证地对了”。更可贵的是文中沉淀出的工程方法论 : 入口宽松、断言严格;在最靠近原因的位置让失败可见;把经验性步骤持续机械化;通过使用驱动迁移而非一次性大审计。对 iOS 团队和所有实践 Agentic Coding 的开发者来说,这篇文章都值得细读。

🐕 Anthropic 产品团队为何快过所有人

@zhangferry:Anthropic 的成功不能简单归功于 Claude Code、Co-Work 这类明星级产品,而是应该着重关注这类产品迭代背后的方法论。这篇文章的访谈嘉宾 Cat Woo 是 Claude Code 和 Co-work 的产品负责人,她系统性地分享了 Claude Code 团队的实战经验。他们的产品是 AI,他们的工作方式也因为 AI 被全面重塑;访谈涵盖了一个核心命题:当模型能力每隔几个月就跃升一次,产品经理的角色该如何重新定义?

🐎 Why Your pbxproj Is Bloated (and How to Fix It)

@david-clang:为什么 .pbxproj 容易臃肿和冲突?因为它记录了所有文件的 UUID,而使用 Groups 会让 Xcode 追踪每一个文件变动。文章介绍的解决办法很简单,用 Folders 代替 Groups,Xcode 只引用目录,不追踪单文件。另外,使用 XcodeGen 也能解决,它将 .xcodeproj 移出 Git,全靠本地按需生成,实现零冲突。

🐕 Six Years Perfecting Maps on watchOS

@Barney:David Smith 在这篇文章里复盘了 Pedometer++ 为 watchOS 打磨地图体验的六年历程,内容很适合拿来理解小屏设备上的产品设计为什么往往是工程能力、交互约束和视觉语言一起决定的。作者最初用服务端生成地图验证方向,随后因为离线能力、性能和交互需求,转向自研基于 SwiftUI 的地图渲染引擎;在界面层面,则经历了大量失败方案,最终收敛到“地图作为顶部主页面,指标信息层叠覆盖”的结构,并通过点击进入浏览模式来解决地图交互与 watchOS 手势冲突。文章后半段也很有意思:为了适配 watchOS 26 的 Liquid Glass,他甚至定制了新的底图与深色模式样式,并解释了为什么最终没有直接采用 MapKit。整体来看,这是一篇把平台限制、设计迭代和技术取舍讲得非常完整的实战复盘。

🐕 Synchronization in Swift: Actors vs Queues vs Locks

@Smallfly:这篇是 Swift 并发同步机制的深度指南,系统对比四类核心同步工具的设计哲学、适用场景与权衡取舍,为开发者构建线程安全代码提供全面决策框架。文章从语言级到硬件级逐层拆解各工具特性:Actors 适合异步环境下的缓存、服务类等状态组件,DispatchQueue 适配依赖执行上下文协调的场景,Locks/Mutexes 性能开销低适合同步小操作,Atomics 则适配计数器、状态标志等单操作场景。文中还给出各工具典型误用的修复方案,打破性能优先的误区,综合安全性、API 设计清晰度、认知负荷等维度给出选择指导,通过场景化分析与可运行示例,帮助开发者理解 Swift 并发同步本质,在复杂系统中做出合理技术选择。

工具

🐎 Cupertino v1.0.0 "First Light"

@阿权:Cupertino MCP 发布 v1.0.0 "First Light" 版本。Cupertino 是一款本地 Apple 文档爬虫 MCP,使用 Swift 编写。用于解决 LLM 对 Apple API 回答幻觉问题,让模型推理时能获取精准、排名合理的 Apple 官方文档,本次版本实现了全流程(爬取、索引、排名、服务、分发)稳定,具体如下:

  1. 搜索准确度大幅提升。优化语料库和权重策略;apple-docs 内部使用 BM25F 算法结合 AST 符 号索引,叠加多个搜索规则以精准命中目标;提升 SQL 性能。
  2. 分发与部署简化。合并三个数据库为单包。
  3. 架构与兼容性提升。数据库升级、MCP 协议升级、爬虫强化。

内推

重新开始更新「iOS 靠谱内推专题」,整理了最近明确在招人的岗位,供大家参考

具体信息请移步:https://www.yuque.com/iosalliance/article/bhutav 进行查看(如有招聘需求请联系 iTDriverr)

关注我们

我们是「老司机技术周报」,一个持续追求精品 iOS 内容的技术公众号,欢迎关注。

关注有礼,关注【老司机技术周报】,回复「2024」,领取 2024 及往年内参

同时也支持了 RSS 订阅:https://github.com/SwiftOldDriver/iOS-Weekly/releases.atom

说明

🚧 表示需某工具,🌟 表示编辑推荐

预计阅读时间:🐎 很快就能读完(1 - 10 mins);🐕 中等 (10 - 20 mins);🐢 慢(20+ mins)

2连板通鼎互联:海南康宁仅作为公司的光棒供应商 不存在其他合作模式

2026年5月10日 16:14
5月10日,通鼎互联公告称,公司股票于2026年5月6日至8日连续三个交易日收盘价格涨幅偏离值累计超过20%,构成异常波动。公司注意到近期市场对光纤光缆行业关注度较高,光纤产品短期价格波动的可持续性具有不确定性,对公司未来业绩的影响需结合未来市场环境及公司业务开展情况进行综合判断,同样存在不确定性。公司用于光纤生产的原材料光纤预制棒(以下简称“光棒”),主要由康宁(海南)光通信有限公司提供。截至目前,海南康宁仅作为公司的光棒供应商,不存在其他合作模式。目前光纤市场景气度同比提升,公司将根据市场需求适当增加产能释放。但光纤复产及扩产需要综合考虑光纤市场价格、供需关系、光棒的供给能力等多方面因素。相关复产及扩产如达到信息披露标准,公司将依据相关规定进行披露。重点提示,如后续市场环境发生变化,存在光纤价格下跌及供需关系变化的风险,请投资者注意风险。(财联社)

宇环数控:不生产航空航天产品的零部件

2026年5月10日 16:13
5月10日,宇环数控公告称,公司股票连续三个交易日(5月6日至5月8日)收盘价格涨幅偏离值累计超过20%,属于股票交易异常波动。公司不生产航空航天产品的零部件。公司主要产品为数控磨削设备、拉削设备等通用机床设备,公司不生产航空航天产品的零部件。公司产品未应用于商业航天领域,部分产品间接应用于航空航天领域,且收入占比较小,对公司业绩的影响程度较小。2026年一季度公司产品间接用于航空航天领域的营业收入为367.26万元,占2026年一季度营业收入比重不足4%。公司产品应用于航空航天领域的业务发展具有较大的不确定性。公司不生产机器人的零部件。公司主要产品为数控磨削设备、拉削设备等通用机床设备,公司不生产机器人的零部件,公司产品在机器人领域的收入占比较小,对公司业绩的影响程度较小。2026年一季度公司产品在机器人领域的营业收入为257.87万元,占2026年一季度营业收入比重不足3%。公司目前无机器人行业的重大在手订单,公司产品应用于机器人领域的业务发展具有较大的不确定性,请投资者审慎决策,注意投资风险。(财联社)

泰坦股份:高端电子布喷气织机尚处于研发阶段 未形成任何销售收入

2026年5月10日 16:13
5月10日,泰坦股份公告称,公司股票连续3个交易日收盘价格涨幅偏离值累计超过20%,属于异常波动。公司关注到近期电子布织机概念受市场关注度较高。截至目前,公司高端电子布喷气织机尚处于研发阶段,未形成任何销售收入,亦存在研发进展不及预期等风险,特别提醒广大投资者,注意投资风险,理性决策,审慎投资。(财联社)

复星医药:控股子公司药品新增适应症获欧盟批准

2026年5月10日 16:12
复星医药公告,近日,公司控股子公司上海复宏汉霖生物技术股份有限公司及其控股子公司自主研发的斯鲁利单抗注射液(欧盟商品名:Hetronifly®)的如下两项新增适应症获欧盟委员会批准:1、联合氟尿嘧啶类及铂类化疗,适用于PD-L1综合阳性评分(CPS)≥5、不可切除的局部晚期、复发或转移性食管鳞状细胞癌(ESCC)成人患者的一线治疗;2、联合卡铂与培美曲塞,适用于EGFR基因突变阴性、ALK或ROS1阴性的不可手术切除的局部晚期或转移性非鳞状非小细胞肺癌(nsNSCLC)成人患者的一线治疗。据此,该等新增适应症已于所有欧盟成员国及冰岛、列支敦士登和挪威(分别为欧洲经济区国家)获得批准。(第一财经)

2025年度全国秋粮收购超3.38亿吨

2026年5月10日 15:25
5月10日,国家粮食和物资储备局最新发布数据显示,2025年度秋粮旺季收购于今年4月底结束,全国各类粮食经营主体累计收购秋粮超3.38亿吨,为近年来较高水平。收购总体呈现进度快、购销活、价格涨等特点。据初步统计,累计收购中晚稻1.03亿吨、玉米2.22亿吨、大豆1299万吨。河南、湖南、黑龙江3省启动中晚稻最低收购价执行预案,累计收购最低收购价中晚稻418万吨。2026年夏粮收购即将展开,国家粮食和物资储备局将加强对夏粮收购形势的分析研判,指导各地和有关企业提前制定收购方案,扎实做好夏粮收购工作准备,全力维护粮食市场平稳运行,促进粮食价格保持在合理水平。 (新华社)

算力、绿能协同悄然提速

2026年5月10日 15:24
5月10日,2026年,算电协同被写入政府工作报告,成为社会关注的热词。“十五五”规划纲要也明确提出,推动绿色电力与算力协同布局。记者近日走访了解到,内蒙古、宁夏、贵州等新能源富集地区,通过布局建设源网荷储一体化、绿电直连等重点项目,充分挖掘西部地区就地消纳潜力,促进新能源与算力设施的协同规划布局。一场算力和绿能的“双向奔赴”正在悄然提速。 (新华社)

中国新增高端聚苯乙烯规模化产能 为光学材料供应链提供新选择

2026年5月10日 15:24
5月10日,中国石油天然气股份有限公司广西石化分公司完全自主研发的光学级聚苯乙烯产品GPPS-550N实现量产。此举意味着全球光学材料供应链上,新增一个具备稳定量产能力、自主工艺和柔性生产特点的中国供应来源。高品质聚苯乙烯GPPS-550N产品具有高透光率、高热稳定性等突出性能,主要面向LED显示器、导光板、高端包装及家电等领域,技术指标达到国际同类产品先进水平。 (中新网)

沙特阿美:即便能源供应恢复 能源体系预计也需要较长时间才能回归常态

2026年5月10日 15:22
5月10日,沙特阿美首席执行官表示,东西管道为阿美赋予了运营灵活性,已被证明是一条关键生命线。部分受影响设施在不到24至48小时内就恢复了生产;若没有前期投资和应急预案,这一过程原本可能需要数月时间。多年投资不足加上近期供应中断,给本已处于低位的全球库存带来了额外压力。即便能源供应恢复,能源体系预计也需要较长时间才能回归常态。

中国新增高端聚苯乙烯规模化产能 为光学材料供应链提供新选择

2026年5月10日 15:01
5月10日,中国石油天然气股份有限公司广西石化分公司完全自主研发的光学级聚苯乙烯产品GPPS-550N实现量产。此举意味着全球光学材料供应链上,新增一个具备稳定量产能力、自主工艺和柔性生产特点的中国供应来源。高品质聚苯乙烯GPPS-550N产品具有高透光率、高热稳定性等突出性能,主要面向LED显示器、导光板、高端包装及家电等领域,技术指标达到国际同类产品先进水平。(证券时报)

华为 Pura X Max 卖爆了,但「阔折叠」还只赢了一半

2026年5月10日 14:17
Image
卖得好,用户「用钱投票」,只是定义一个好产品的关键指标之一。

作者|张勇毅

编辑|靖宇
 

4 月 25 日上午 10 点 08 分,华为 Pura X Max 正式开售。10999 元起步,12999 元的典藏版比标准版贵 2000 元。

十天之后,第三方监测数据公布了更多细节——典藏版占首销总量的 55%,标准版只占 45%。

越贵的版本,反而卖得更多。

这是 2026 年上半年中国手机市场少见的反常画面。同一时段里,整个行业的基调是「涨价、收缩、分化」——但一台万元起步的折叠屏旗舰,不仅卖爆了,而且越贵的型号卖得越好。

余承东在北京车展上的原话是「卖爆了」。随后有媒体援引华为内部数据:首销日激活 7 万+、3 天 11 万+、7 天 17 万+、10 天 20 万+,每一档都是折叠屏品类的历史最高。

Image

华为 Pura X Max|图片来源:极客公园

 

这台机器是华为口中的「行业首款横向阔折叠」。余承东在发布会上把它的形态正式命名为「阔折叠」。

但比起单纯堆数据,我更想搞清楚一件事:Pura X Max 卖爆了,是不是意味着「阔折叠」这个形态被市场认可了?

这两件事看起来是一回事,其实不是。

01

反常的不是绝对值

 

首销十天 20 万台,这个绝对值放在整个智能手机市场,并不算骇人——同期任何一款主流直板旗舰首销都能超过它。

数据反常的地方是相对值。

据博主 @RD观测 的数据,Pura X Max 首销日的销量约为 Pura X 同期的 215%,首周是 180%。截至 5 月 4 日,较 Mate X7 同期提升 61%,较 Pura X 同期提升 45%。

Mate X7 是华为 2025 年 11 月发布的横向大折叠旗舰,是华为传统折叠屏的「重型」产品线,定价段位高于 Pura X 系列。Pura X Max 在它面前 +61%——这意味着 Pura X Max 其实已经在蚕食华为自家的传统折叠屏需求池。

它在吸引新用户的同时,也从 Mate X7 手里挖走了相当一部分原本会选 Mate X7 的老用户。

而典藏版 55% 的占比则给出了另一个信号——这群肯多花 2000 块的用户,不是在「冲销量」,他们认这台机器,并且愿意为更完整的版本付溢价。在 2026 年这个高端机型普遍「涨价遇冷」的市场里,这种价格分布反常本身就是一个独立的产品力背书。

Image

华为 Pura X Max |图片来源:极客公园

 

把绝对值(20 万台)、相对值(+61% / +45%)、内部蚕食(vs Mate X7)、价格分布(典藏版 55%)这四组数据摆在一起,结论其实很清楚:Pura X Max 这台产品本身是成功的。

把镜头从 Pura X Max 这台机器拉远一点:2026 年的折叠屏市场,目前在售的「阔折叠」产品只有一款:华为 Pura X Max。它的前代 Pura X,是另一款阔折叠产品,但已经接近停产周期。三星、苹果、OPPO、vivo、小米、荣耀,目前没有任何一家厂商在卖同形态产品。

这意味着一件事——Pura X Max 的销量再高,能证明的也只是「华为做阔折叠行」,而不是「阔折叠这个形态行」。

一个形态如果只有一个玩家在卖,无论卖得多好,都还不能叫品类共识。

02

用户、同行与苹果

 

用户层面「用钱投票」认可,是过去一年最确定的部分。

IDC 的数据显示,截至 2026 年 3 月底,上市一年间,华为 Pura X 出货量突破 150 万台,单款产品出货量超过其后三位厂商旗舰折叠机型产品的总和。

这是一个跨越式的数字。在折叠屏整体仍是个低个位数比例的小众市场里(折叠屏占整体智能手机出货比例至今未突破 5%),一款单品做到这个量,意味着 Pura X 抓住了一个真实存在的用户群。

我之前写过一篇关于 Pura X Max 的稿子,里面提到一个细节:在 Pura X 上市之后,小红书上慢慢沉淀出一种特殊的用法——主要是女性用户,她们买了 Pura X 之后,会再配一个固定硬壳,把它常态锁在展开状态下使用,几乎不合上。

简单说,就是把这台一万元的折叠屏,当成一台屏幕比例特殊的直屏机来用。

这件事的反讽意味在于——折叠屏过去七年的核心叙事,是「同一台设备的两种形态」「手机和平板二合一」。所有厂商的发布会上,最高光的镜头永远是机身合起或打开的那个瞬间。

但 Pura X 的部分用户用脚投票投出来的结论是:他们要的不是「二合一」,是那块比例对的大屏。

Pura X Max 在这群人的基础上,又往前走了一步——把内屏从手机的边界推过了平板的边界(7.7 英寸,已经接近 iPad mini 的 8.3 英寸)。所以 Pura X Max 首销 +45% 这个数字背后,其实是 Pura X 时代的用户在升级,加上一批被 Pura X 验证之后才决定下场的新用户。

同行层面的情况,比用户层面复杂得多。

跟得最明确的是三星。据 ET News 在 2025 年底的报道,三星正在开发一款代号 Wide Fold 的产品,计划 2026 年秋季推出,展开后是 7.6 英寸 4:3 比例的内屏,折叠后是 5.4 英寸外屏。

Image

三星版「阔折叠」屏幕比例与 Pura X Max 高度相似|图片来源:UniverseIce

 

这个参数和 Pura X Max 的形态高度重合——三星这次没有继续走传统的 Z Fold 路线,而是单独开了一条阔折叠产品线。

这是过去七年里,三星折叠屏战略上的一次显著调整。

但除了三星之外,其他主要厂商目前都还在「计划」「传闻」阶段。

在 2025 年底曾行业消息称,OPPO、vivo、小米、荣耀都计划在 2026 年推出阔折叠手机。但截至目前,这些产品没有一款落地。如今我们真正看到的「阔折叠」,还只有 Pura X Max 一款

OV 米荣这种「先观望、再下场」的姿态,在中国手机厂商里并不少见,本身是一个理性的商业选择——但它也意味着,目前还没有哪一家国产厂商,敢像三星那样,把自己未来 12 个月的旗舰押在阔折叠这个形态上。

同行这一票,三星投了,但 OV 米荣还在观望。所以最多算半票。

最关键的那一票,是苹果。

天风国际证券分析师郭明錤在过去一年里多次披露苹果折叠 iPhone 的供应链信息。最关键的一条是关于形态的:这台代号为 iPhone Fold 的产品,走的是 book-style 左右开,不是阔折叠。

Image

折叠屏 iPhone 与一开始预期的「阔折叠」实际尺寸上有明显差距|图片来源:macrumors

 

具体形态是——折叠时外屏 5.5 英寸(接近常规手机比例),展开时内屏 7.8 英寸(接近正方形)。这种形态接近三星传统的 Galaxy Z Fold 系列,本质是「左右翻书」,而不是华为这种「平板对折成横向大屏」。

苹果的产品节奏,目前供应链口径是 2026 年下半年发布、但因为开发滞后,量产可能要拖到 2027 年。Counterpoint 预测苹果折叠 iPhone 首批出货量在 800 万到 1000 万台之间,2027 年扩大到 2000 万。

这个量级会迅速重新定义整个折叠屏市场的竞争格局。

但这里有一个常被忽略的事实:苹果这台机器的形态选择,不是「阔折叠」,而是 book-style。 也就是说,折叠屏市场里量级最重、品牌号召力最强、最有可能定义品类标准的那个玩家,没有把票投给阔折叠。

这一票不是反对,是弃权——苹果选了另一条路。

而苹果选的这条路,意味着另一种叙事:折叠屏是一台「能展开的手机」,不是一台「能装进口袋的小平板」。

哪种叙事会赢?现在没有答案。

03

答案是「一半」

 

把三票放在一起看,「阔折叠是否被认可」这个问题的答案就清楚了:用户层面赢了,同行层面赢了一半,对手层面没投票。

加起来,是一半的胜利。

这一半的胜利,足够让 Pura X Max 在 2026 年的窗口期里独自领跑——目前阔折叠形态没有第二个在售对手,它在这条路上是唯一的玩家,销量和用户教育都做得起来。但要把这一半补成完整的胜利,需要在接下来 12 到 18 个月里发生两件事:

第一,三星 2026 年秋季的 Wide Fold 真的落地,并且销量能跟上。如果三星这台机器卖得好,「阔折叠」就有了第二个独立验证的玩家,OV 米荣会迅速跟进。

第二,苹果在 2027 年的折叠 iPhone 之后,是不是会推出第二代——而第二代的形态选择是不是会向阔折叠靠拢。 苹果第一代选 book-style 是供应链、铰链工艺、生态适配的综合考量,第二代有调整空间。如果 2028 年苹果出一款 √2:1 比例的折叠 iPhone,那「阔折叠」就有了真正的品类共识。

这两件事如果都发生,Pura X Max 在 2026 年这个时间点,会被记成华为「定义阔折叠并赢下整个赛道」的起点。如果只发生一件,它仍然是 2026 年最成功的折叠屏,但「阔折叠 = 折叠屏下一代」这个命题成立的可能性会被打折。

Image

华为 Pura X Max|图片来源:极客公园

 

所以现在能下的判断只有这一句:阔折叠在用户层面赢了,在同行层面赢了一半,在最重要的玩家那里还没拿到票。 销量数据说明华为的产品力没有问题,但形态层面的胜负还没有终局答案。

要等到 2026 年底回头看——三星 Wide Fold 卖得怎么样、OV 米荣有没有跟进、以及苹果 iPhone Fold 的市场反应是什么——才能真正判断这一半的胜利能不能补成完整的一票。

*头图来源:极客公园
本文为极客公园原创文章,转载请联系极客君微信 geekparkGO
极客一问
你认为「阔折叠」会不会成为
折叠屏的下一代主流形态?
Image
Image
Image
Image

 

深圳一直播销售改装电动自行车“黑窝点”被端 12人被刑拘

2026年5月10日 14:10
自2025年12月1日电动自行车新国标全面实施以来,深圳市市场监管局共立案457宗,扣押不合格电动自行车1062辆、相关配件1656件,罚没款73.33万元,移送公安机关3宗。4月份,深圳市市场监管局联合市公安交管部门,成功打掉一个利用网络直播平台非法生产销售改装电动自行车的“黑窝点”,共刑拘犯罪嫌疑人12名。同时,联合公安交管等部门和街道在坪山区现场查获不符合国家强制性标准的电动自行车592辆,为新国标实施以来深圳市扣押车辆数最多的一宗不合格电动自行车案。 (央视新闻)
❌
❌